1cd4e3c3eSJouni Malinen /*
2cd4e3c3eSJouni Malinen * Sigma Control API DUT (station/AP)
3659a34c4SAmarnath Hullur Subramanyam * Copyright (c) 2014-2017, Qualcomm Atheros, Inc.
41bde7947SAnkita Bajaj * Copyright (c) 2018, The Linux Foundation
5a37dc16cSAlexei Avshalom Lazar * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
6cd4e3c3eSJouni Malinen * All Rights Reserved.
7cd4e3c3eSJouni Malinen * Licensed under the Clear BSD license. See README for more details.
8cd4e3c3eSJouni Malinen */
9cd4e3c3eSJouni Malinen
10cd4e3c3eSJouni Malinen #include "sigma_dut.h"
1154b78cfdSVinita Maloo #include <sys/ioctl.h>
12cd4e3c3eSJouni Malinen #include <sys/stat.h>
13cd4e3c3eSJouni Malinen #include "wpa_helpers.h"
14cd4e3c3eSJouni Malinen
15cd4e3c3eSJouni Malinen enum driver_type wifi_chip_type = DRIVER_NOT_SET;
16cd4e3c3eSJouni Malinen enum openwrt_driver_type openwrt_chip_type = OPENWRT_DRIVER_NOT_SET;
17cd4e3c3eSJouni Malinen
1854b78cfdSVinita Maloo struct wcn_drv_priv_cmd {
1954b78cfdSVinita Maloo char *buf;
2054b78cfdSVinita Maloo int used_len;
2154b78cfdSVinita Maloo int total_len;
2254b78cfdSVinita Maloo };
23cd4e3c3eSJouni Malinen
file_exists(const char * fname)24cd4e3c3eSJouni Malinen int file_exists(const char *fname)
25cd4e3c3eSJouni Malinen {
26cd4e3c3eSJouni Malinen struct stat s;
27cd4e3c3eSJouni Malinen return stat(fname, &s) == 0;
28cd4e3c3eSJouni Malinen }
29cd4e3c3eSJouni Malinen
30cd4e3c3eSJouni Malinen
set_wifi_chip(const char * chip_type)31cd4e3c3eSJouni Malinen int set_wifi_chip(const char *chip_type)
32cd4e3c3eSJouni Malinen {
33cd4e3c3eSJouni Malinen if (!strncmp(chip_type, "WCN", strlen("WCN")))
34cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_WCN;
35cd4e3c3eSJouni Malinen else if (!strncmp(chip_type, "ATHEROS", strlen("ATHEROS")))
36cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_ATHEROS;
37cd4e3c3eSJouni Malinen else if (!strncmp(chip_type, "AR6003", strlen("AR6003")))
38cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_AR6003;
39cd4e3c3eSJouni Malinen else if (strcmp(chip_type, "MAC80211") == 0)
40cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_MAC80211;
41cd4e3c3eSJouni Malinen else if (strcmp(chip_type, "QNXNTO") == 0)
42cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_QNXNTO;
43cd4e3c3eSJouni Malinen else if (strcmp(chip_type, "OPENWRT") == 0)
44cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_OPENWRT;
45b692f107SSreelakshmi Konamki else if (!strncmp(chip_type, "LINUX-WCN", strlen("LINUX-WCN")))
46b692f107SSreelakshmi Konamki wifi_chip_type = DRIVER_LINUX_WCN;
47cd4e3c3eSJouni Malinen else
48cd4e3c3eSJouni Malinen return -1;
49cd4e3c3eSJouni Malinen
50cd4e3c3eSJouni Malinen return 0;
51cd4e3c3eSJouni Malinen }
52cd4e3c3eSJouni Malinen
53cd4e3c3eSJouni Malinen
get_driver_type(struct sigma_dut * dut)54016ae6c8SJouni Malinen enum driver_type get_driver_type(struct sigma_dut *dut)
55cd4e3c3eSJouni Malinen {
56cd4e3c3eSJouni Malinen struct stat s;
57cd4e3c3eSJouni Malinen if (wifi_chip_type == DRIVER_NOT_SET) {
58cd4e3c3eSJouni Malinen /* Check for 60G driver */
59cd4e3c3eSJouni Malinen ssize_t len;
60cd4e3c3eSJouni Malinen char link[256];
61cd4e3c3eSJouni Malinen char buf[256];
62016ae6c8SJouni Malinen const char *ifname = get_station_ifname(dut);
63cd4e3c3eSJouni Malinen
64cd4e3c3eSJouni Malinen snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver",
65cd4e3c3eSJouni Malinen ifname);
66cd4e3c3eSJouni Malinen len = readlink(buf, link, sizeof(link) - 1);
67cd4e3c3eSJouni Malinen if (len >= 0) {
68cd4e3c3eSJouni Malinen link[len] = '\0';
69cd4e3c3eSJouni Malinen if (strstr(link, DRIVER_NAME_60G))
70cd4e3c3eSJouni Malinen return DRIVER_WIL6210;
71cd4e3c3eSJouni Malinen }
72cd4e3c3eSJouni Malinen
73cd4e3c3eSJouni Malinen if (stat("/sys/module/mac80211", &s) == 0)
74cd4e3c3eSJouni Malinen return DRIVER_MAC80211;
75cd4e3c3eSJouni Malinen return DRIVER_ATHEROS;
76cd4e3c3eSJouni Malinen }
77cd4e3c3eSJouni Malinen return wifi_chip_type;
78cd4e3c3eSJouni Malinen }
79cd4e3c3eSJouni Malinen
80cd4e3c3eSJouni Malinen
sigma_dut_get_device_driver_name(const char * ifname,char * name,size_t size)81*f0f8805aSVenkateswara Naralasetty void sigma_dut_get_device_driver_name(const char *ifname, char *name,
82*f0f8805aSVenkateswara Naralasetty size_t size)
83*f0f8805aSVenkateswara Naralasetty {
84*f0f8805aSVenkateswara Naralasetty char fname[128], path[128];
85*f0f8805aSVenkateswara Naralasetty struct stat s;
86*f0f8805aSVenkateswara Naralasetty ssize_t res;
87*f0f8805aSVenkateswara Naralasetty char *pos;
88*f0f8805aSVenkateswara Naralasetty
89*f0f8805aSVenkateswara Naralasetty name[0] = '\0';
90*f0f8805aSVenkateswara Naralasetty
91*f0f8805aSVenkateswara Naralasetty snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname);
92*f0f8805aSVenkateswara Naralasetty if (stat(path, &s) != 0)
93*f0f8805aSVenkateswara Naralasetty return;
94*f0f8805aSVenkateswara Naralasetty
95*f0f8805aSVenkateswara Naralasetty res = snprintf(fname, sizeof(fname),
96*f0f8805aSVenkateswara Naralasetty "/sys/class/net/%s/device/driver", ifname);
97*f0f8805aSVenkateswara Naralasetty if (res < 0 || res >= sizeof(fname))
98*f0f8805aSVenkateswara Naralasetty return;
99*f0f8805aSVenkateswara Naralasetty res = readlink(fname, path, sizeof(path));
100*f0f8805aSVenkateswara Naralasetty if (res < 0)
101*f0f8805aSVenkateswara Naralasetty return;
102*f0f8805aSVenkateswara Naralasetty
103*f0f8805aSVenkateswara Naralasetty if (res >= (int) sizeof(path))
104*f0f8805aSVenkateswara Naralasetty res = sizeof(path) - 1;
105*f0f8805aSVenkateswara Naralasetty path[res] = '\0';
106*f0f8805aSVenkateswara Naralasetty pos = strrchr(path, '/');
107*f0f8805aSVenkateswara Naralasetty if (!pos)
108*f0f8805aSVenkateswara Naralasetty pos = path;
109*f0f8805aSVenkateswara Naralasetty else
110*f0f8805aSVenkateswara Naralasetty pos++;
111*f0f8805aSVenkateswara Naralasetty snprintf(name, size, "%s", pos);
112*f0f8805aSVenkateswara Naralasetty }
113*f0f8805aSVenkateswara Naralasetty
114*f0f8805aSVenkateswara Naralasetty
get_openwrt_driver_type(void)115cd4e3c3eSJouni Malinen enum openwrt_driver_type get_openwrt_driver_type(void)
116cd4e3c3eSJouni Malinen {
117cd4e3c3eSJouni Malinen struct stat s;
118cd4e3c3eSJouni Malinen
119cd4e3c3eSJouni Malinen if (openwrt_chip_type == OPENWRT_DRIVER_NOT_SET) {
12000bbdf1bSpriyadharshini gowthaman if (stat("/sys/module/umac", &s) == 0 ||
12100bbdf1bSpriyadharshini gowthaman stat("/sys/module/atd", &s) == 0)
122cd4e3c3eSJouni Malinen openwrt_chip_type = OPENWRT_DRIVER_ATHEROS;
123cd4e3c3eSJouni Malinen }
124cd4e3c3eSJouni Malinen
125cd4e3c3eSJouni Malinen return openwrt_chip_type;
126cd4e3c3eSJouni Malinen }
127cd4e3c3eSJouni Malinen
128cd4e3c3eSJouni Malinen
sigma_program_to_enum(const char * prog)129cd4e3c3eSJouni Malinen enum sigma_program sigma_program_to_enum(const char *prog)
130cd4e3c3eSJouni Malinen {
131cd4e3c3eSJouni Malinen if (prog == NULL)
132cd4e3c3eSJouni Malinen return PROGRAM_UNKNOWN;
133cd4e3c3eSJouni Malinen
134cd4e3c3eSJouni Malinen if (strcasecmp(prog, "TDLS") == 0)
135cd4e3c3eSJouni Malinen return PROGRAM_TDLS;
136cd4e3c3eSJouni Malinen if (strcasecmp(prog, "HS2") == 0)
137cd4e3c3eSJouni Malinen return PROGRAM_HS2;
138cd4e3c3eSJouni Malinen if (strcasecmp(prog, "HS2_R2") == 0 ||
139ba630459SJouni Malinen strcasecmp(prog, "HS2-R2") == 0)
140cd4e3c3eSJouni Malinen return PROGRAM_HS2_R2;
141ba630459SJouni Malinen if (strcasecmp(prog, "HS2-R3") == 0)
142ba630459SJouni Malinen return PROGRAM_HS2_R3;
143cd4e3c3eSJouni Malinen if (strcasecmp(prog, "WFD") == 0)
144cd4e3c3eSJouni Malinen return PROGRAM_WFD;
145659a34c4SAmarnath Hullur Subramanyam if (strcasecmp(prog, "DisplayR2") == 0)
146659a34c4SAmarnath Hullur Subramanyam return PROGRAM_DISPLAYR2;
147cd4e3c3eSJouni Malinen if (strcasecmp(prog, "PMF") == 0)
148cd4e3c3eSJouni Malinen return PROGRAM_PMF;
149cd4e3c3eSJouni Malinen if (strcasecmp(prog, "WPS") == 0)
150cd4e3c3eSJouni Malinen return PROGRAM_WPS;
151cd4e3c3eSJouni Malinen if (strcasecmp(prog, "11n") == 0)
152cd4e3c3eSJouni Malinen return PROGRAM_HT;
153cd4e3c3eSJouni Malinen if (strcasecmp(prog, "VHT") == 0)
154cd4e3c3eSJouni Malinen return PROGRAM_VHT;
155cd4e3c3eSJouni Malinen if (strcasecmp(prog, "60GHZ") == 0)
156cd4e3c3eSJouni Malinen return PROGRAM_60GHZ;
157cd4e3c3eSJouni Malinen if (strcasecmp(prog, "NAN") == 0)
158cd4e3c3eSJouni Malinen return PROGRAM_NAN;
15912dd4145Spriyadharshini gowthaman if (strcasecmp(prog, "LOC") == 0)
16012dd4145Spriyadharshini gowthaman return PROGRAM_LOC;
161b4e05fc1Spriyadharshini gowthaman if (strcasecmp(prog, "MBO") == 0)
162b4e05fc1Spriyadharshini gowthaman return PROGRAM_MBO;
16333ea287aSAdil Saeed Musthafa if (strcasecmp(prog, "IoTLP") == 0)
16433ea287aSAdil Saeed Musthafa return PROGRAM_IOTLP;
1655c3813a7SJouni Malinen if (strcasecmp(prog, "DPP") == 0)
1665c3813a7SJouni Malinen return PROGRAM_DPP;
167a2cb567bSAnkita Bajaj if (strcasecmp(prog, "OCE") == 0)
168a2cb567bSAnkita Bajaj return PROGRAM_OCE;
1690e209fccSpriyadharshini gowthaman if (strcasecmp(prog, "WPA3") == 0)
1700e209fccSpriyadharshini gowthaman return PROGRAM_WPA3;
1718f9c8687SAmarnath Hullur Subramanyam if (strcasecmp(prog, "HE") == 0)
1728f9c8687SAmarnath Hullur Subramanyam return PROGRAM_HE;
173f642d6adSVamsi Krishna if (strcasecmp(prog, "QM") == 0)
174f642d6adSVamsi Krishna return PROGRAM_QM;
175cd4e3c3eSJouni Malinen
176cd4e3c3eSJouni Malinen return PROGRAM_UNKNOWN;
177cd4e3c3eSJouni Malinen }
17872462ef3Spriyadharshini gowthaman
17972462ef3Spriyadharshini gowthaman
parse_hex(char c)18072462ef3Spriyadharshini gowthaman static int parse_hex(char c)
18172462ef3Spriyadharshini gowthaman {
18272462ef3Spriyadharshini gowthaman if (c >= '0' && c <= '9')
18372462ef3Spriyadharshini gowthaman return c - '0';
18472462ef3Spriyadharshini gowthaman if (c >= 'a' && c <= 'f')
18572462ef3Spriyadharshini gowthaman return c - 'a' + 10;
18672462ef3Spriyadharshini gowthaman if (c >= 'A' && c <= 'F')
18772462ef3Spriyadharshini gowthaman return c - 'A' + 10;
18872462ef3Spriyadharshini gowthaman return -1;
18972462ef3Spriyadharshini gowthaman }
19072462ef3Spriyadharshini gowthaman
19172462ef3Spriyadharshini gowthaman
hex_byte(const char * str)1929a4f98d9SAlexei Avshalom Lazar int hex_byte(const char *str)
19372462ef3Spriyadharshini gowthaman {
19472462ef3Spriyadharshini gowthaman int res1, res2;
19572462ef3Spriyadharshini gowthaman
19672462ef3Spriyadharshini gowthaman res1 = parse_hex(str[0]);
19772462ef3Spriyadharshini gowthaman if (res1 < 0)
19872462ef3Spriyadharshini gowthaman return -1;
19972462ef3Spriyadharshini gowthaman res2 = parse_hex(str[1]);
20072462ef3Spriyadharshini gowthaman if (res2 < 0)
20172462ef3Spriyadharshini gowthaman return -1;
20272462ef3Spriyadharshini gowthaman return (res1 << 4) | res2;
20372462ef3Spriyadharshini gowthaman }
20472462ef3Spriyadharshini gowthaman
20572462ef3Spriyadharshini gowthaman
parse_hexstr(const char * hex,unsigned char * buf,size_t buflen)20608cf231dSJouni Malinen int parse_hexstr(const char *hex, unsigned char *buf, size_t buflen)
20708cf231dSJouni Malinen {
20808cf231dSJouni Malinen size_t i;
20908cf231dSJouni Malinen const char *pos = hex;
21008cf231dSJouni Malinen
21108cf231dSJouni Malinen for (i = 0; i < buflen; i++) {
21208cf231dSJouni Malinen int val;
21308cf231dSJouni Malinen
21408cf231dSJouni Malinen if (*pos == '\0')
21508cf231dSJouni Malinen break;
21608cf231dSJouni Malinen val = hex_byte(pos);
21708cf231dSJouni Malinen if (val < 0)
21808cf231dSJouni Malinen return -1;
21908cf231dSJouni Malinen buf[i] = val;
22008cf231dSJouni Malinen pos += 2;
22108cf231dSJouni Malinen }
22208cf231dSJouni Malinen
22308cf231dSJouni Malinen return i;
22408cf231dSJouni Malinen }
22508cf231dSJouni Malinen
22608cf231dSJouni Malinen
parse_mac_address(struct sigma_dut * dut,const char * arg,unsigned char * addr)22772462ef3Spriyadharshini gowthaman int parse_mac_address(struct sigma_dut *dut, const char *arg,
22872462ef3Spriyadharshini gowthaman unsigned char *addr)
22972462ef3Spriyadharshini gowthaman {
23072462ef3Spriyadharshini gowthaman int i;
23172462ef3Spriyadharshini gowthaman const char *pos = arg;
23272462ef3Spriyadharshini gowthaman
23372462ef3Spriyadharshini gowthaman if (strlen(arg) != 17)
23472462ef3Spriyadharshini gowthaman goto fail;
23572462ef3Spriyadharshini gowthaman
23672462ef3Spriyadharshini gowthaman for (i = 0; i < ETH_ALEN; i++) {
23772462ef3Spriyadharshini gowthaman int val;
23872462ef3Spriyadharshini gowthaman
23972462ef3Spriyadharshini gowthaman val = hex_byte(pos);
24072462ef3Spriyadharshini gowthaman if (val < 0)
24172462ef3Spriyadharshini gowthaman goto fail;
24272462ef3Spriyadharshini gowthaman addr[i] = val;
24372462ef3Spriyadharshini gowthaman if (i + 1 < ETH_ALEN) {
24472462ef3Spriyadharshini gowthaman pos += 2;
24572462ef3Spriyadharshini gowthaman if (*pos != ':')
24672462ef3Spriyadharshini gowthaman goto fail;
24772462ef3Spriyadharshini gowthaman pos++;
24872462ef3Spriyadharshini gowthaman }
24972462ef3Spriyadharshini gowthaman }
25072462ef3Spriyadharshini gowthaman
25172462ef3Spriyadharshini gowthaman return 0;
25272462ef3Spriyadharshini gowthaman
25372462ef3Spriyadharshini gowthaman fail:
25472462ef3Spriyadharshini gowthaman sigma_dut_print(dut, DUT_MSG_ERROR,
25572462ef3Spriyadharshini gowthaman "Invalid MAC address %s (expected format xx:xx:xx:xx:xx:xx)",
25672462ef3Spriyadharshini gowthaman arg);
25772462ef3Spriyadharshini gowthaman return -1;
25872462ef3Spriyadharshini gowthaman }
2597192dc42SRakesh Sunki
2607192dc42SRakesh Sunki
is_60g_sigma_dut(struct sigma_dut * dut)261093569ffSAlexei Avshalom Lazar int is_60g_sigma_dut(struct sigma_dut *dut)
2627192dc42SRakesh Sunki {
263093569ffSAlexei Avshalom Lazar return dut->program == PROGRAM_60GHZ ||
264093569ffSAlexei Avshalom Lazar (dut->program == PROGRAM_WPS &&
265016ae6c8SJouni Malinen (get_driver_type(dut) == DRIVER_WIL6210));
266093569ffSAlexei Avshalom Lazar }
267093569ffSAlexei Avshalom Lazar
268093569ffSAlexei Avshalom Lazar
channel_to_freq(struct sigma_dut * dut,unsigned int channel)269093569ffSAlexei Avshalom Lazar unsigned int channel_to_freq(struct sigma_dut *dut, unsigned int channel)
270093569ffSAlexei Avshalom Lazar {
271093569ffSAlexei Avshalom Lazar if (is_60g_sigma_dut(dut)) {
272093569ffSAlexei Avshalom Lazar if (channel >= 1 && channel <= 4)
273093569ffSAlexei Avshalom Lazar return 58320 + 2160 * channel;
274093569ffSAlexei Avshalom Lazar
275093569ffSAlexei Avshalom Lazar return 0;
276093569ffSAlexei Avshalom Lazar }
277093569ffSAlexei Avshalom Lazar
2787192dc42SRakesh Sunki if (channel >= 1 && channel <= 13)
2797192dc42SRakesh Sunki return 2407 + 5 * channel;
2807192dc42SRakesh Sunki if (channel == 14)
2817192dc42SRakesh Sunki return 2484;
2827192dc42SRakesh Sunki if (channel >= 36 && channel <= 165)
2837192dc42SRakesh Sunki return 5000 + 5 * channel;
2847192dc42SRakesh Sunki
2857192dc42SRakesh Sunki return 0;
2867192dc42SRakesh Sunki }
2877192dc42SRakesh Sunki
2887192dc42SRakesh Sunki
freq_to_channel(unsigned int freq)2897192dc42SRakesh Sunki unsigned int freq_to_channel(unsigned int freq)
2907192dc42SRakesh Sunki {
2917192dc42SRakesh Sunki if (freq >= 2412 && freq <= 2472)
2927192dc42SRakesh Sunki return (freq - 2407) / 5;
2937192dc42SRakesh Sunki if (freq == 2484)
2947192dc42SRakesh Sunki return 14;
2957192dc42SRakesh Sunki if (freq >= 5180 && freq <= 5825)
2967192dc42SRakesh Sunki return (freq - 5000) / 5;
297093569ffSAlexei Avshalom Lazar if (freq >= 58320 && freq <= 64800)
298093569ffSAlexei Avshalom Lazar return (freq - 58320) / 2160;
2997192dc42SRakesh Sunki return 0;
3007192dc42SRakesh Sunki }
301769731a2SPeng Xu
302769731a2SPeng Xu
is_ipv6_addr(const char * str)303525965bbSPeng Xu int is_ipv6_addr(const char *str)
304525965bbSPeng Xu {
305525965bbSPeng Xu struct sockaddr_in6 addr;
306525965bbSPeng Xu
307525965bbSPeng Xu return inet_pton(AF_INET6, str, &(addr.sin6_addr));
308525965bbSPeng Xu }
309525965bbSPeng Xu
310525965bbSPeng Xu
convert_mac_addr_to_ipv6_lladdr(u8 * mac_addr,char * ipv6_buf,size_t buf_len)3118f8e74b5SRakesh Sunki void convert_mac_addr_to_ipv6_lladdr(u8 *mac_addr, char *ipv6_buf,
3128f8e74b5SRakesh Sunki size_t buf_len)
3138f8e74b5SRakesh Sunki {
3148f8e74b5SRakesh Sunki u8 temp = mac_addr[0] ^ 0x02;
3158f8e74b5SRakesh Sunki
3168f8e74b5SRakesh Sunki snprintf(ipv6_buf, buf_len, "fe80::%02x%02x:%02xff:fe%02x:%02x%02x",
3178f8e74b5SRakesh Sunki temp, mac_addr[1], mac_addr[2],
3188f8e74b5SRakesh Sunki mac_addr[3], mac_addr[4], mac_addr[5]);
3198f8e74b5SRakesh Sunki }
3208f8e74b5SRakesh Sunki
3218f8e74b5SRakesh Sunki
convert_mac_addr_to_ipv6_linklocal(const u8 * mac_addr,u8 * ipv6)3228863ec7cSPeng Xu size_t convert_mac_addr_to_ipv6_linklocal(const u8 *mac_addr, u8 *ipv6)
3238863ec7cSPeng Xu {
3248863ec7cSPeng Xu int i;
3258863ec7cSPeng Xu
3268863ec7cSPeng Xu ipv6[0] = 0xfe;
3278863ec7cSPeng Xu ipv6[1] = 0x80;
3288863ec7cSPeng Xu for (i = 2; i < 8; i++)
3298863ec7cSPeng Xu ipv6[i] = 0;
3308863ec7cSPeng Xu ipv6[8] = mac_addr[0] ^ 0x02;
3318863ec7cSPeng Xu ipv6[9] = mac_addr[1];
3328863ec7cSPeng Xu ipv6[10] = mac_addr[2];
3338863ec7cSPeng Xu ipv6[11] = 0xff;
3348863ec7cSPeng Xu ipv6[12] = 0xfe;
3358863ec7cSPeng Xu ipv6[13] = mac_addr[3];
3368863ec7cSPeng Xu ipv6[14] = mac_addr[4];
3378863ec7cSPeng Xu ipv6[15] = mac_addr[5];
3388863ec7cSPeng Xu
3398863ec7cSPeng Xu return 16;
3408863ec7cSPeng Xu }
3418863ec7cSPeng Xu
3428863ec7cSPeng Xu
343769731a2SPeng Xu #ifndef ANDROID
344769731a2SPeng Xu
strlcpy(char * dest,const char * src,size_t siz)345769731a2SPeng Xu size_t strlcpy(char *dest, const char *src, size_t siz)
346769731a2SPeng Xu {
347769731a2SPeng Xu const char *s = src;
348769731a2SPeng Xu size_t left = siz;
349769731a2SPeng Xu
350769731a2SPeng Xu if (left) {
351769731a2SPeng Xu /* Copy string up to the maximum size of the dest buffer */
352769731a2SPeng Xu while (--left != 0) {
353769731a2SPeng Xu if ((*dest++ = *s++) == '\0')
354769731a2SPeng Xu break;
355769731a2SPeng Xu }
356769731a2SPeng Xu }
357769731a2SPeng Xu
358769731a2SPeng Xu if (left == 0) {
359769731a2SPeng Xu /* Not enough room for the string; force NUL-termination */
360769731a2SPeng Xu if (siz != 0)
361769731a2SPeng Xu *dest = '\0';
362769731a2SPeng Xu while (*s++)
363769731a2SPeng Xu ; /* determine total src string length */
364769731a2SPeng Xu }
365769731a2SPeng Xu
366769731a2SPeng Xu return s - src - 1;
367769731a2SPeng Xu }
368769731a2SPeng Xu
369769731a2SPeng Xu
strlcat(char * dst,const char * str,size_t size)370769731a2SPeng Xu size_t strlcat(char *dst, const char *str, size_t size)
371769731a2SPeng Xu {
372769731a2SPeng Xu char *pos;
373769731a2SPeng Xu size_t dstlen, srclen, copy;
374769731a2SPeng Xu
375769731a2SPeng Xu srclen = strlen(str);
376769731a2SPeng Xu for (pos = dst; pos - dst < size && *dst; pos++)
377769731a2SPeng Xu ;
378769731a2SPeng Xu dstlen = pos - dst;
379769731a2SPeng Xu if (*dst)
380769731a2SPeng Xu return dstlen + srclen;
381769731a2SPeng Xu if (dstlen + srclen + 1 > size)
382769731a2SPeng Xu copy = size - dstlen - 1;
383769731a2SPeng Xu else
384769731a2SPeng Xu copy = srclen;
385769731a2SPeng Xu memcpy(pos, str, copy);
386769731a2SPeng Xu pos[copy] = '\0';
387769731a2SPeng Xu return dstlen + srclen;
388769731a2SPeng Xu }
389769731a2SPeng Xu
390769731a2SPeng Xu #endif /* ANDROID */
3911bde7947SAnkita Bajaj
3921bde7947SAnkita Bajaj
hex_dump(struct sigma_dut * dut,u8 * data,size_t len)3931bde7947SAnkita Bajaj void hex_dump(struct sigma_dut *dut, u8 *data, size_t len)
3941bde7947SAnkita Bajaj {
3951bde7947SAnkita Bajaj char buf[1024];
3961bde7947SAnkita Bajaj size_t index;
3971bde7947SAnkita Bajaj u8 *ptr;
3981bde7947SAnkita Bajaj int pos;
3991bde7947SAnkita Bajaj
4001bde7947SAnkita Bajaj memset(buf, 0, sizeof(buf));
4011bde7947SAnkita Bajaj ptr = data;
4021bde7947SAnkita Bajaj pos = 0;
4031bde7947SAnkita Bajaj for (index = 0; index < len; index++) {
4041bde7947SAnkita Bajaj pos += snprintf(&(buf[pos]), sizeof(buf) - pos,
4051bde7947SAnkita Bajaj "%02x ", *ptr++);
4061bde7947SAnkita Bajaj if (pos > 1020)
4071bde7947SAnkita Bajaj break;
4081bde7947SAnkita Bajaj }
4091bde7947SAnkita Bajaj sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len);
4101bde7947SAnkita Bajaj sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf);
4111bde7947SAnkita Bajaj }
412291d97daSPeng Xu
413291d97daSPeng Xu
414291d97daSPeng Xu #ifdef NL80211_SUPPORT
415291d97daSPeng Xu
nl80211_cmd(struct sigma_dut * dut,struct nl80211_ctx * ctx,struct nl_msg * msg,int flags,uint8_t cmd)416291d97daSPeng Xu void * nl80211_cmd(struct sigma_dut *dut, struct nl80211_ctx *ctx,
417291d97daSPeng Xu struct nl_msg *msg, int flags, uint8_t cmd)
418291d97daSPeng Xu {
419291d97daSPeng Xu return genlmsg_put(msg, 0, 0, ctx->netlink_familyid,
420291d97daSPeng Xu 0, flags, cmd, 0);
421291d97daSPeng Xu }
422291d97daSPeng Xu
423291d97daSPeng Xu
424291d97daSPeng Xu static struct nl_msg *
nl80211_ifindex_msg(struct sigma_dut * dut,struct nl80211_ctx * ctx,int ifindex,int flags,uint8_t cmd)425291d97daSPeng Xu nl80211_ifindex_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx, int ifindex,
426291d97daSPeng Xu int flags, uint8_t cmd)
427291d97daSPeng Xu {
428291d97daSPeng Xu struct nl_msg *msg;
429291d97daSPeng Xu
430291d97daSPeng Xu msg = nlmsg_alloc();
431291d97daSPeng Xu if (!msg) {
432291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_ERROR,
433291d97daSPeng Xu "Failed to allocate NL message");
434291d97daSPeng Xu return NULL;
435291d97daSPeng Xu }
436291d97daSPeng Xu
437291d97daSPeng Xu if (!nl80211_cmd(dut, ctx, msg, flags, cmd) ||
438291d97daSPeng Xu nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
439291d97daSPeng Xu nlmsg_free(msg);
440291d97daSPeng Xu return NULL;
441291d97daSPeng Xu }
442291d97daSPeng Xu
443291d97daSPeng Xu return msg;
444291d97daSPeng Xu }
445291d97daSPeng Xu
446291d97daSPeng Xu
nl80211_drv_msg(struct sigma_dut * dut,struct nl80211_ctx * ctx,int ifindex,int flags,uint8_t cmd)447291d97daSPeng Xu struct nl_msg * nl80211_drv_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx,
448291d97daSPeng Xu int ifindex, int flags, uint8_t cmd)
449291d97daSPeng Xu {
450291d97daSPeng Xu return nl80211_ifindex_msg(dut, ctx, ifindex, flags, cmd);
451291d97daSPeng Xu }
452291d97daSPeng Xu
453291d97daSPeng Xu
ack_handler(struct nl_msg * msg,void * arg)454291d97daSPeng Xu static int ack_handler(struct nl_msg *msg, void *arg)
455291d97daSPeng Xu {
456291d97daSPeng Xu int *err = arg;
457291d97daSPeng Xu *err = 0;
458291d97daSPeng Xu return NL_STOP;
459291d97daSPeng Xu }
460291d97daSPeng Xu
461291d97daSPeng Xu
finish_handler(struct nl_msg * msg,void * arg)462291d97daSPeng Xu static int finish_handler(struct nl_msg *msg, void *arg)
463291d97daSPeng Xu {
464291d97daSPeng Xu int *ret = arg;
465291d97daSPeng Xu *ret = 0;
466291d97daSPeng Xu return NL_SKIP;
467291d97daSPeng Xu }
468291d97daSPeng Xu
469291d97daSPeng Xu
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)470291d97daSPeng Xu static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
471291d97daSPeng Xu void *arg)
472291d97daSPeng Xu {
473291d97daSPeng Xu int *ret = arg;
474291d97daSPeng Xu *ret = err->error;
475291d97daSPeng Xu return NL_SKIP;
476291d97daSPeng Xu }
477291d97daSPeng Xu
478291d97daSPeng Xu
send_and_recv_msgs(struct sigma_dut * dut,struct nl80211_ctx * ctx,struct nl_msg * nlmsg,int (* valid_handler)(struct nl_msg *,void *),void * valid_data)479291d97daSPeng Xu int send_and_recv_msgs(struct sigma_dut *dut, struct nl80211_ctx *ctx,
480291d97daSPeng Xu struct nl_msg *nlmsg,
481291d97daSPeng Xu int (*valid_handler)(struct nl_msg *, void *),
482291d97daSPeng Xu void *valid_data)
483291d97daSPeng Xu {
484291d97daSPeng Xu struct nl_cb *cb;
485291d97daSPeng Xu int err = -ENOMEM;
486291d97daSPeng Xu
487291d97daSPeng Xu if (!nlmsg)
488291d97daSPeng Xu return -ENOMEM;
489291d97daSPeng Xu
490291d97daSPeng Xu cb = nl_cb_alloc(NL_CB_DEFAULT);
491291d97daSPeng Xu if (!cb)
492291d97daSPeng Xu goto out;
493291d97daSPeng Xu
494291d97daSPeng Xu err = nl_send_auto_complete(ctx->sock, nlmsg);
495291d97daSPeng Xu if (err < 0) {
496291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_ERROR,
497291d97daSPeng Xu "nl80211: failed to send err=%d", err);
498291d97daSPeng Xu goto out;
499291d97daSPeng Xu }
500291d97daSPeng Xu
501291d97daSPeng Xu err = 1;
502291d97daSPeng Xu
503291d97daSPeng Xu nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
504291d97daSPeng Xu nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
505291d97daSPeng Xu nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
506291d97daSPeng Xu
507291d97daSPeng Xu if (valid_handler)
508291d97daSPeng Xu nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
509291d97daSPeng Xu valid_handler, valid_data);
510291d97daSPeng Xu
511291d97daSPeng Xu while (err > 0) {
512291d97daSPeng Xu int res = nl_recvmsgs(ctx->sock, cb);
513291d97daSPeng Xu
514291d97daSPeng Xu if (res < 0) {
515291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_ERROR,
516291d97daSPeng Xu "nl80211: %s->nl_recvmsgs failed: res=%d, err=%d",
517291d97daSPeng Xu __func__, res, err);
518291d97daSPeng Xu }
519291d97daSPeng Xu }
520291d97daSPeng Xu out:
521291d97daSPeng Xu nl_cb_put(cb);
522291d97daSPeng Xu if (!valid_handler && valid_data == (void *) -1) {
523291d97daSPeng Xu if (nlmsg) {
524291d97daSPeng Xu struct nlmsghdr *hdr = nlmsg_hdr(nlmsg);
525291d97daSPeng Xu void *data = nlmsg_data(hdr);
526291d97daSPeng Xu int len = hdr->nlmsg_len - NLMSG_HDRLEN;
527291d97daSPeng Xu
528291d97daSPeng Xu memset(data, 0, len);
529291d97daSPeng Xu }
530291d97daSPeng Xu }
531291d97daSPeng Xu
532291d97daSPeng Xu nlmsg_free(nlmsg);
533291d97daSPeng Xu return err;
534291d97daSPeng Xu }
535291d97daSPeng Xu
536291d97daSPeng Xu
nl80211_init(struct sigma_dut * dut)537291d97daSPeng Xu struct nl80211_ctx * nl80211_init(struct sigma_dut *dut)
538291d97daSPeng Xu {
539291d97daSPeng Xu struct nl80211_ctx *ctx;
540291d97daSPeng Xu
541291d97daSPeng Xu ctx = calloc(1, sizeof(struct nl80211_ctx));
542291d97daSPeng Xu if (!ctx) {
543291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_ERROR,
544291d97daSPeng Xu "Failed to alloc nl80211_ctx");
545291d97daSPeng Xu return NULL;
546291d97daSPeng Xu }
547291d97daSPeng Xu
548291d97daSPeng Xu ctx->sock = nl_socket_alloc();
549291d97daSPeng Xu if (!ctx->sock) {
550291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_ERROR,
551291d97daSPeng Xu "Failed to create NL socket, err: %s",
552291d97daSPeng Xu strerror(errno));
553291d97daSPeng Xu goto cleanup;
554291d97daSPeng Xu }
555291d97daSPeng Xu
556291d97daSPeng Xu if (nl_connect(ctx->sock, NETLINK_GENERIC)) {
557291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_ERROR,
558291d97daSPeng Xu "Could not connect socket, err: %s",
559291d97daSPeng Xu strerror(errno));
560291d97daSPeng Xu goto cleanup;
561291d97daSPeng Xu }
562291d97daSPeng Xu
563291d97daSPeng Xu if (nl_socket_set_buffer_size(ctx->sock, SOCK_BUF_SIZE, 0) < 0) {
564291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_INFO,
565291d97daSPeng Xu "Could not set nl_socket RX buffer size for sock: %s",
566291d97daSPeng Xu strerror(errno));
567291d97daSPeng Xu }
568291d97daSPeng Xu
569291d97daSPeng Xu ctx->netlink_familyid = genl_ctrl_resolve(ctx->sock, "nl80211");
570291d97daSPeng Xu if (ctx->netlink_familyid < 0) {
571291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_ERROR,
572291d97daSPeng Xu "Could not resolve nl80211 family id");
573291d97daSPeng Xu goto cleanup;
574291d97daSPeng Xu }
575291d97daSPeng Xu
576291d97daSPeng Xu ctx->nlctrl_familyid = genl_ctrl_resolve(ctx->sock, "nlctrl");
577291d97daSPeng Xu if (ctx->nlctrl_familyid < 0) {
578291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_ERROR,
579291d97daSPeng Xu "net link family nlctrl is not present: %d err:%s",
580291d97daSPeng Xu ctx->nlctrl_familyid, strerror(errno));
581291d97daSPeng Xu goto cleanup;
582291d97daSPeng Xu }
583291d97daSPeng Xu
584291d97daSPeng Xu return ctx;
585291d97daSPeng Xu
586291d97daSPeng Xu cleanup:
587291d97daSPeng Xu if (ctx->sock)
588291d97daSPeng Xu nl_socket_free(ctx->sock);
589291d97daSPeng Xu
590291d97daSPeng Xu free(ctx);
591291d97daSPeng Xu return NULL;
592291d97daSPeng Xu }
593291d97daSPeng Xu
594291d97daSPeng Xu
nl80211_deinit(struct sigma_dut * dut,struct nl80211_ctx * ctx)595291d97daSPeng Xu void nl80211_deinit(struct sigma_dut *dut, struct nl80211_ctx *ctx)
596291d97daSPeng Xu {
597291d97daSPeng Xu if (!ctx || !ctx->sock) {
598291d97daSPeng Xu sigma_dut_print(dut, DUT_MSG_ERROR, "%s: ctx/sock is NULL",
599291d97daSPeng Xu __func__);
600291d97daSPeng Xu return;
601291d97daSPeng Xu }
602291d97daSPeng Xu nl_socket_free(ctx->sock);
603291d97daSPeng Xu free(ctx);
604291d97daSPeng Xu }
605291d97daSPeng Xu
606050b85a6SVeerendranath Jakkam
607050b85a6SVeerendranath Jakkam static struct nl_msg *
wcn_create_wifi_test_config_msg(struct sigma_dut * dut,const char * intf)608050b85a6SVeerendranath Jakkam wcn_create_wifi_test_config_msg(struct sigma_dut *dut, const char *intf)
609050b85a6SVeerendranath Jakkam {
610050b85a6SVeerendranath Jakkam int ifindex;
611050b85a6SVeerendranath Jakkam struct nl_msg *msg;
612050b85a6SVeerendranath Jakkam
613050b85a6SVeerendranath Jakkam ifindex = if_nametoindex(intf);
614050b85a6SVeerendranath Jakkam if (ifindex == 0) {
615050b85a6SVeerendranath Jakkam sigma_dut_print(dut, DUT_MSG_ERROR,
616050b85a6SVeerendranath Jakkam "%s: Index for interface %s failed",
617050b85a6SVeerendranath Jakkam __func__, intf);
618050b85a6SVeerendranath Jakkam return NULL;
619050b85a6SVeerendranath Jakkam }
620050b85a6SVeerendranath Jakkam
621050b85a6SVeerendranath Jakkam if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
622050b85a6SVeerendranath Jakkam NL80211_CMD_VENDOR)) ||
623050b85a6SVeerendranath Jakkam nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
624050b85a6SVeerendranath Jakkam nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
625050b85a6SVeerendranath Jakkam nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
626050b85a6SVeerendranath Jakkam QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION)) {
627050b85a6SVeerendranath Jakkam nlmsg_free(msg);
628050b85a6SVeerendranath Jakkam return NULL;
629050b85a6SVeerendranath Jakkam }
630050b85a6SVeerendranath Jakkam
631050b85a6SVeerendranath Jakkam return msg;
632050b85a6SVeerendranath Jakkam }
633050b85a6SVeerendranath Jakkam
634050b85a6SVeerendranath Jakkam
wcn_send_wifi_test_config_msg(struct sigma_dut * dut,struct nl_msg * msg,struct nlattr * params,int attr_id)635050b85a6SVeerendranath Jakkam static int wcn_send_wifi_test_config_msg(struct sigma_dut *dut,
636050b85a6SVeerendranath Jakkam struct nl_msg *msg,
637050b85a6SVeerendranath Jakkam struct nlattr *params, int attr_id)
638050b85a6SVeerendranath Jakkam {
639050b85a6SVeerendranath Jakkam int ret;
640050b85a6SVeerendranath Jakkam
641050b85a6SVeerendranath Jakkam nla_nest_end(msg, params);
642050b85a6SVeerendranath Jakkam
643050b85a6SVeerendranath Jakkam ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
644050b85a6SVeerendranath Jakkam if (ret) {
645050b85a6SVeerendranath Jakkam sigma_dut_print(dut, DUT_MSG_ERROR,
646050b85a6SVeerendranath Jakkam "%s: err in send_and_recv_msgs, ret=%d for %d",
647050b85a6SVeerendranath Jakkam __func__, ret, attr_id);
648050b85a6SVeerendranath Jakkam }
649050b85a6SVeerendranath Jakkam
650050b85a6SVeerendranath Jakkam return ret;
651050b85a6SVeerendranath Jakkam }
652050b85a6SVeerendranath Jakkam
653050b85a6SVeerendranath Jakkam
wcn_wifi_test_config_set_flag(struct sigma_dut * dut,const char * intf,int attr_id)654050b85a6SVeerendranath Jakkam int wcn_wifi_test_config_set_flag(struct sigma_dut *dut, const char *intf,
655050b85a6SVeerendranath Jakkam int attr_id)
656050b85a6SVeerendranath Jakkam {
657050b85a6SVeerendranath Jakkam struct nl_msg *msg;
658050b85a6SVeerendranath Jakkam struct nlattr *params;
659050b85a6SVeerendranath Jakkam
660050b85a6SVeerendranath Jakkam if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
661050b85a6SVeerendranath Jakkam !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
662050b85a6SVeerendranath Jakkam nla_put_flag(msg, attr_id)) {
663050b85a6SVeerendranath Jakkam sigma_dut_print(dut, DUT_MSG_ERROR,
664050b85a6SVeerendranath Jakkam "%s: err in adding test config data for %d",
665050b85a6SVeerendranath Jakkam __func__, attr_id);
666050b85a6SVeerendranath Jakkam nlmsg_free(msg);
667050b85a6SVeerendranath Jakkam return -1;
668050b85a6SVeerendranath Jakkam }
669050b85a6SVeerendranath Jakkam
670050b85a6SVeerendranath Jakkam return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
671050b85a6SVeerendranath Jakkam }
672050b85a6SVeerendranath Jakkam
673050b85a6SVeerendranath Jakkam
wcn_wifi_test_config_set_u8(struct sigma_dut * dut,const char * intf,int attr_id,uint8_t val)674050b85a6SVeerendranath Jakkam int wcn_wifi_test_config_set_u8(struct sigma_dut *dut, const char *intf,
675050b85a6SVeerendranath Jakkam int attr_id, uint8_t val)
676050b85a6SVeerendranath Jakkam {
677050b85a6SVeerendranath Jakkam struct nl_msg *msg;
678050b85a6SVeerendranath Jakkam struct nlattr *params;
679050b85a6SVeerendranath Jakkam
680050b85a6SVeerendranath Jakkam if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
681050b85a6SVeerendranath Jakkam !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
682050b85a6SVeerendranath Jakkam nla_put_u8(msg, attr_id, val)) {
683050b85a6SVeerendranath Jakkam sigma_dut_print(dut, DUT_MSG_ERROR,
684050b85a6SVeerendranath Jakkam "%s: err in adding test config data for %d",
685050b85a6SVeerendranath Jakkam __func__, attr_id);
686050b85a6SVeerendranath Jakkam nlmsg_free(msg);
687050b85a6SVeerendranath Jakkam return -1;
688050b85a6SVeerendranath Jakkam }
689050b85a6SVeerendranath Jakkam
690050b85a6SVeerendranath Jakkam return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
691050b85a6SVeerendranath Jakkam }
692050b85a6SVeerendranath Jakkam
693050b85a6SVeerendranath Jakkam
wcn_wifi_test_config_set_u16(struct sigma_dut * dut,const char * intf,int attr_id,uint16_t val)694050b85a6SVeerendranath Jakkam int wcn_wifi_test_config_set_u16(struct sigma_dut *dut, const char *intf,
695050b85a6SVeerendranath Jakkam int attr_id, uint16_t val)
696050b85a6SVeerendranath Jakkam {
697050b85a6SVeerendranath Jakkam struct nl_msg *msg;
698050b85a6SVeerendranath Jakkam struct nlattr *params;
699050b85a6SVeerendranath Jakkam
700050b85a6SVeerendranath Jakkam if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
701050b85a6SVeerendranath Jakkam !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
702050b85a6SVeerendranath Jakkam nla_put_u16(msg, attr_id, val)) {
703050b85a6SVeerendranath Jakkam sigma_dut_print(dut, DUT_MSG_ERROR,
704050b85a6SVeerendranath Jakkam "%s: err in adding test config data for %d",
705050b85a6SVeerendranath Jakkam __func__, attr_id);
706050b85a6SVeerendranath Jakkam nlmsg_free(msg);
707050b85a6SVeerendranath Jakkam return -1;
708050b85a6SVeerendranath Jakkam }
709050b85a6SVeerendranath Jakkam
710050b85a6SVeerendranath Jakkam return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
711050b85a6SVeerendranath Jakkam }
712050b85a6SVeerendranath Jakkam
713291d97daSPeng Xu #endif /* NL80211_SUPPORT */
7146427969bSAlexei Avshalom Lazar
7156427969bSAlexei Avshalom Lazar
get_wps_pin_checksum(int pin)7160dae51c5SAlexei Avshalom Lazar static int get_wps_pin_checksum(int pin)
7170dae51c5SAlexei Avshalom Lazar {
7180dae51c5SAlexei Avshalom Lazar int a = 0;
7190dae51c5SAlexei Avshalom Lazar
7200dae51c5SAlexei Avshalom Lazar while (pin > 0) {
7210dae51c5SAlexei Avshalom Lazar a += 3 * (pin % 10);
7220dae51c5SAlexei Avshalom Lazar pin = pin / 10;
7230dae51c5SAlexei Avshalom Lazar a += (pin % 10);
7240dae51c5SAlexei Avshalom Lazar pin = pin / 10;
7250dae51c5SAlexei Avshalom Lazar }
7260dae51c5SAlexei Avshalom Lazar
7270dae51c5SAlexei Avshalom Lazar return (10 - (a % 10)) % 10;
7280dae51c5SAlexei Avshalom Lazar }
7290dae51c5SAlexei Avshalom Lazar
7300dae51c5SAlexei Avshalom Lazar
get_wps_pin_from_mac(struct sigma_dut * dut,const char * macaddr,char * pin,size_t len)7310dae51c5SAlexei Avshalom Lazar int get_wps_pin_from_mac(struct sigma_dut *dut, const char *macaddr,
7320dae51c5SAlexei Avshalom Lazar char *pin, size_t len)
7330dae51c5SAlexei Avshalom Lazar {
7340dae51c5SAlexei Avshalom Lazar unsigned char mac[ETH_ALEN];
7350dae51c5SAlexei Avshalom Lazar int tmp, checksum;
7360dae51c5SAlexei Avshalom Lazar
7370dae51c5SAlexei Avshalom Lazar if (len < 9)
7380dae51c5SAlexei Avshalom Lazar return -1;
7390dae51c5SAlexei Avshalom Lazar if (parse_mac_address(dut, macaddr, mac))
7400dae51c5SAlexei Avshalom Lazar return -1;
7410dae51c5SAlexei Avshalom Lazar
7420dae51c5SAlexei Avshalom Lazar /*
7430dae51c5SAlexei Avshalom Lazar * get 7 digit PIN from the last 24 bits of MAC
7440dae51c5SAlexei Avshalom Lazar * range 1000000 - 9999999
7450dae51c5SAlexei Avshalom Lazar */
7460dae51c5SAlexei Avshalom Lazar tmp = (mac[5] & 0xFF) | ((mac[4] & 0xFF) << 8) |
7470dae51c5SAlexei Avshalom Lazar ((mac[3] & 0xFF) << 16);
7480dae51c5SAlexei Avshalom Lazar tmp = (tmp % 9000000) + 1000000;
7490dae51c5SAlexei Avshalom Lazar checksum = get_wps_pin_checksum(tmp);
7500dae51c5SAlexei Avshalom Lazar snprintf(pin, len, "%07d%01d", tmp, checksum);
7510dae51c5SAlexei Avshalom Lazar return 0;
7520dae51c5SAlexei Avshalom Lazar }
7530dae51c5SAlexei Avshalom Lazar
7540dae51c5SAlexei Avshalom Lazar
get_wps_forced_version(struct sigma_dut * dut,const char * str)755744ae8abSAlexei Avshalom Lazar int get_wps_forced_version(struct sigma_dut *dut, const char *str)
756744ae8abSAlexei Avshalom Lazar {
757744ae8abSAlexei Avshalom Lazar int major, minor, result = 0;
758744ae8abSAlexei Avshalom Lazar int count = sscanf(str, "%d.%d", &major, &minor);
759744ae8abSAlexei Avshalom Lazar
760744ae8abSAlexei Avshalom Lazar if (count == 2) {
761744ae8abSAlexei Avshalom Lazar result = major * 16 + minor;
762744ae8abSAlexei Avshalom Lazar sigma_dut_print(dut, DUT_MSG_DEBUG,
763744ae8abSAlexei Avshalom Lazar "Force WPS version to 0x%02x (%s)",
764744ae8abSAlexei Avshalom Lazar result, str);
765744ae8abSAlexei Avshalom Lazar } else {
766744ae8abSAlexei Avshalom Lazar sigma_dut_print(dut, DUT_MSG_ERROR,
767744ae8abSAlexei Avshalom Lazar "Invalid WPS version %s", str);
768744ae8abSAlexei Avshalom Lazar }
769744ae8abSAlexei Avshalom Lazar
770744ae8abSAlexei Avshalom Lazar return result;
771744ae8abSAlexei Avshalom Lazar }
772744ae8abSAlexei Avshalom Lazar
773744ae8abSAlexei Avshalom Lazar
str_remove_chars(char * str,char ch)7746427969bSAlexei Avshalom Lazar void str_remove_chars(char *str, char ch)
7756427969bSAlexei Avshalom Lazar {
7766427969bSAlexei Avshalom Lazar char *pr = str, *pw = str;
7776427969bSAlexei Avshalom Lazar
7786427969bSAlexei Avshalom Lazar while (*pr) {
7796427969bSAlexei Avshalom Lazar *pw = *pr++;
7806427969bSAlexei Avshalom Lazar if (*pw != ch)
7816427969bSAlexei Avshalom Lazar pw++;
7826427969bSAlexei Avshalom Lazar }
7836427969bSAlexei Avshalom Lazar *pw = '\0';
7846427969bSAlexei Avshalom Lazar }
785a37dc16cSAlexei Avshalom Lazar
786a37dc16cSAlexei Avshalom Lazar
787a37dc16cSAlexei Avshalom Lazar static const char base64_table[65] =
788a37dc16cSAlexei Avshalom Lazar "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
789a37dc16cSAlexei Avshalom Lazar
790a37dc16cSAlexei Avshalom Lazar
base64_encode(const char * src,size_t len,char * out,size_t out_len)791a37dc16cSAlexei Avshalom Lazar int base64_encode(const char *src, size_t len, char *out, size_t out_len)
792a37dc16cSAlexei Avshalom Lazar {
793a37dc16cSAlexei Avshalom Lazar unsigned char *pos;
794a37dc16cSAlexei Avshalom Lazar const unsigned char *end, *in;
795a37dc16cSAlexei Avshalom Lazar size_t olen;
796a37dc16cSAlexei Avshalom Lazar
797a37dc16cSAlexei Avshalom Lazar olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
798a37dc16cSAlexei Avshalom Lazar olen++; /* nul termination */
799a37dc16cSAlexei Avshalom Lazar if (olen < len || olen > out_len)
800a37dc16cSAlexei Avshalom Lazar return -1;
801a37dc16cSAlexei Avshalom Lazar
802a37dc16cSAlexei Avshalom Lazar end = (unsigned char *)(src + len);
803a37dc16cSAlexei Avshalom Lazar in = (unsigned char *)src;
804a37dc16cSAlexei Avshalom Lazar pos = (unsigned char *)out;
805a37dc16cSAlexei Avshalom Lazar while (end - in >= 3) {
806a37dc16cSAlexei Avshalom Lazar *pos++ = base64_table[(in[0] >> 2) & 0x3f];
807a37dc16cSAlexei Avshalom Lazar *pos++ = base64_table[(((in[0] & 0x03) << 4) |
808a37dc16cSAlexei Avshalom Lazar (in[1] >> 4)) & 0x3f];
809a37dc16cSAlexei Avshalom Lazar *pos++ = base64_table[(((in[1] & 0x0f) << 2) |
810a37dc16cSAlexei Avshalom Lazar (in[2] >> 6)) & 0x3f];
811a37dc16cSAlexei Avshalom Lazar *pos++ = base64_table[in[2] & 0x3f];
812a37dc16cSAlexei Avshalom Lazar in += 3;
813a37dc16cSAlexei Avshalom Lazar }
814a37dc16cSAlexei Avshalom Lazar
815a37dc16cSAlexei Avshalom Lazar if (end - in) {
816a37dc16cSAlexei Avshalom Lazar *pos++ = base64_table[(in[0] >> 2) & 0x3f];
817a37dc16cSAlexei Avshalom Lazar if (end - in == 1) {
818a37dc16cSAlexei Avshalom Lazar *pos++ = base64_table[((in[0] & 0x03) << 4) & 0x3f];
819a37dc16cSAlexei Avshalom Lazar *pos++ = '=';
820a37dc16cSAlexei Avshalom Lazar } else {
821a37dc16cSAlexei Avshalom Lazar *pos++ = base64_table[(((in[0] & 0x03) << 4) |
822a37dc16cSAlexei Avshalom Lazar (in[1] >> 4)) & 0x3f];
823a37dc16cSAlexei Avshalom Lazar *pos++ = base64_table[((in[1] & 0x0f) << 2) & 0x3f];
824a37dc16cSAlexei Avshalom Lazar }
825a37dc16cSAlexei Avshalom Lazar *pos++ = '=';
826a37dc16cSAlexei Avshalom Lazar }
827a37dc16cSAlexei Avshalom Lazar
828a37dc16cSAlexei Avshalom Lazar *pos = '\0';
829a37dc16cSAlexei Avshalom Lazar return 0;
830a37dc16cSAlexei Avshalom Lazar }
831a37dc16cSAlexei Avshalom Lazar
832a37dc16cSAlexei Avshalom Lazar
random_get_bytes(char * buf,size_t len)833a37dc16cSAlexei Avshalom Lazar int random_get_bytes(char *buf, size_t len)
834a37dc16cSAlexei Avshalom Lazar {
835a37dc16cSAlexei Avshalom Lazar FILE *f;
836a37dc16cSAlexei Avshalom Lazar size_t rc;
837a37dc16cSAlexei Avshalom Lazar
838a37dc16cSAlexei Avshalom Lazar f = fopen("/dev/urandom", "rb");
839a37dc16cSAlexei Avshalom Lazar if (!f)
840a37dc16cSAlexei Avshalom Lazar return -1;
841a37dc16cSAlexei Avshalom Lazar
842a37dc16cSAlexei Avshalom Lazar rc = fread(buf, 1, len, f);
843a37dc16cSAlexei Avshalom Lazar fclose(f);
844a37dc16cSAlexei Avshalom Lazar
845a37dc16cSAlexei Avshalom Lazar return rc != len ? -1 : 0;
846a37dc16cSAlexei Avshalom Lazar }
8473c740ab7SJouni Malinen
8483c740ab7SJouni Malinen
get_enable_disable(const char * val)8493c740ab7SJouni Malinen int get_enable_disable(const char *val)
8503c740ab7SJouni Malinen {
8513c740ab7SJouni Malinen if (strcasecmp(val, "enable") == 0 ||
8523c740ab7SJouni Malinen strcasecmp(val, "enabled") == 0 ||
8533c740ab7SJouni Malinen strcasecmp(val, "on") == 0 ||
8543c740ab7SJouni Malinen strcasecmp(val, "yes") == 0)
8553c740ab7SJouni Malinen return 1;
8563c740ab7SJouni Malinen return atoi(val);
8573c740ab7SJouni Malinen }
85854b78cfdSVinita Maloo
85954b78cfdSVinita Maloo
wcn_driver_cmd(const char * ifname,char * buf)86054b78cfdSVinita Maloo int wcn_driver_cmd(const char *ifname, char *buf)
86154b78cfdSVinita Maloo {
86254b78cfdSVinita Maloo int s, res;
86354b78cfdSVinita Maloo size_t buf_len;
86454b78cfdSVinita Maloo struct wcn_drv_priv_cmd priv_cmd;
86554b78cfdSVinita Maloo struct ifreq ifr;
86654b78cfdSVinita Maloo
86754b78cfdSVinita Maloo s = socket(PF_INET, SOCK_DGRAM, 0);
86854b78cfdSVinita Maloo if (s < 0) {
86954b78cfdSVinita Maloo perror("socket");
87054b78cfdSVinita Maloo return -1;
87154b78cfdSVinita Maloo }
87254b78cfdSVinita Maloo
87354b78cfdSVinita Maloo memset(&ifr, 0, sizeof(ifr));
87454b78cfdSVinita Maloo memset(&priv_cmd, 0, sizeof(priv_cmd));
87554b78cfdSVinita Maloo strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
87654b78cfdSVinita Maloo buf_len = strlen(buf);
87754b78cfdSVinita Maloo priv_cmd.buf = buf;
87854b78cfdSVinita Maloo priv_cmd.used_len = buf_len;
87954b78cfdSVinita Maloo priv_cmd.total_len = buf_len;
88054b78cfdSVinita Maloo ifr.ifr_data = (void *) &priv_cmd;
88154b78cfdSVinita Maloo res = ioctl(s, SIOCDEVPRIVATE + 1, &ifr);
88254b78cfdSVinita Maloo close(s);
88354b78cfdSVinita Maloo return res;
88454b78cfdSVinita Maloo }
885176181c5SVeerendranath Jakkam
886176181c5SVeerendranath Jakkam
set_ipv6_addr(struct sigma_dut * dut,const char * ip,const char * mask,const char * ifname)887176181c5SVeerendranath Jakkam int set_ipv6_addr(struct sigma_dut *dut, const char *ip, const char *mask,
888176181c5SVeerendranath Jakkam const char *ifname)
889176181c5SVeerendranath Jakkam {
890176181c5SVeerendranath Jakkam char buf[200];
891176181c5SVeerendranath Jakkam
892176181c5SVeerendranath Jakkam snprintf(buf, sizeof(buf), "ip -6 addr del %s/%s dev %s", ip, mask,
893176181c5SVeerendranath Jakkam ifname);
894176181c5SVeerendranath Jakkam sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
895176181c5SVeerendranath Jakkam if (system(buf) != 0) {
896176181c5SVeerendranath Jakkam /*
897176181c5SVeerendranath Jakkam * This command may fail if the address being deleted does not
898176181c5SVeerendranath Jakkam * exist. Inaction here is intentional.
899176181c5SVeerendranath Jakkam */
900176181c5SVeerendranath Jakkam }
901176181c5SVeerendranath Jakkam
902176181c5SVeerendranath Jakkam snprintf(buf, sizeof(buf), "ip -6 addr add %s/%s dev %s", ip, mask,
903176181c5SVeerendranath Jakkam ifname);
904176181c5SVeerendranath Jakkam sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
905176181c5SVeerendranath Jakkam if (system(buf) != 0)
906176181c5SVeerendranath Jakkam return -1;
907176181c5SVeerendranath Jakkam
908176181c5SVeerendranath Jakkam return 0;
909176181c5SVeerendranath Jakkam }
910