xref: /wlan-dirver/utils/sigma-dut/utils.c (revision f0f8805aa32da5a7803079812d520cc99bf02da7)
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