xref: /wlan-dirver/utils/sigma-dut/utils.c (revision 0e209fccdde535b0c65101a0138d250ffdece3ed)
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
5cd4e3c3eSJouni Malinen  * All Rights Reserved.
6cd4e3c3eSJouni Malinen  * Licensed under the Clear BSD license. See README for more details.
7cd4e3c3eSJouni Malinen  */
8cd4e3c3eSJouni Malinen 
9cd4e3c3eSJouni Malinen #include "sigma_dut.h"
10cd4e3c3eSJouni Malinen #include <sys/stat.h>
11cd4e3c3eSJouni Malinen #include "wpa_helpers.h"
12cd4e3c3eSJouni Malinen 
13cd4e3c3eSJouni Malinen enum driver_type wifi_chip_type = DRIVER_NOT_SET;
14cd4e3c3eSJouni Malinen enum openwrt_driver_type openwrt_chip_type = OPENWRT_DRIVER_NOT_SET;
15cd4e3c3eSJouni Malinen 
16cd4e3c3eSJouni Malinen 
17cd4e3c3eSJouni Malinen int file_exists(const char *fname)
18cd4e3c3eSJouni Malinen {
19cd4e3c3eSJouni Malinen 	struct stat s;
20cd4e3c3eSJouni Malinen 	return stat(fname, &s) == 0;
21cd4e3c3eSJouni Malinen }
22cd4e3c3eSJouni Malinen 
23cd4e3c3eSJouni Malinen 
24cd4e3c3eSJouni Malinen int set_wifi_chip(const char *chip_type)
25cd4e3c3eSJouni Malinen {
26cd4e3c3eSJouni Malinen 	if (!strncmp(chip_type, "WCN", strlen("WCN")))
27cd4e3c3eSJouni Malinen 		wifi_chip_type = DRIVER_WCN;
28cd4e3c3eSJouni Malinen 	else if (!strncmp(chip_type, "ATHEROS", strlen("ATHEROS")))
29cd4e3c3eSJouni Malinen 		wifi_chip_type = DRIVER_ATHEROS;
30cd4e3c3eSJouni Malinen 	else if (!strncmp(chip_type, "AR6003", strlen("AR6003")))
31cd4e3c3eSJouni Malinen 		wifi_chip_type = DRIVER_AR6003;
32cd4e3c3eSJouni Malinen 	else if (strcmp(chip_type, "MAC80211") == 0)
33cd4e3c3eSJouni Malinen 		wifi_chip_type = DRIVER_MAC80211;
34cd4e3c3eSJouni Malinen 	else if (strcmp(chip_type, "QNXNTO") == 0)
35cd4e3c3eSJouni Malinen 		wifi_chip_type = DRIVER_QNXNTO;
36cd4e3c3eSJouni Malinen 	else if (strcmp(chip_type, "OPENWRT") == 0)
37cd4e3c3eSJouni Malinen 		wifi_chip_type = DRIVER_OPENWRT;
38b692f107SSreelakshmi Konamki 	else if (!strncmp(chip_type, "LINUX-WCN", strlen("LINUX-WCN")))
39b692f107SSreelakshmi Konamki 		wifi_chip_type = DRIVER_LINUX_WCN;
40cd4e3c3eSJouni Malinen 	else
41cd4e3c3eSJouni Malinen 		return -1;
42cd4e3c3eSJouni Malinen 
43cd4e3c3eSJouni Malinen 	return 0;
44cd4e3c3eSJouni Malinen }
45cd4e3c3eSJouni Malinen 
46cd4e3c3eSJouni Malinen 
47cd4e3c3eSJouni Malinen enum driver_type get_driver_type(void)
48cd4e3c3eSJouni Malinen {
49cd4e3c3eSJouni Malinen 	struct stat s;
50cd4e3c3eSJouni Malinen 	if (wifi_chip_type == DRIVER_NOT_SET) {
51cd4e3c3eSJouni Malinen 		/* Check for 60G driver */
52cd4e3c3eSJouni Malinen 		ssize_t len;
53cd4e3c3eSJouni Malinen 		char link[256];
54cd4e3c3eSJouni Malinen 		char buf[256];
55cd4e3c3eSJouni Malinen 		char *ifname = get_station_ifname();
56cd4e3c3eSJouni Malinen 
57cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver",
58cd4e3c3eSJouni Malinen 			 ifname);
59cd4e3c3eSJouni Malinen 		len = readlink(buf, link, sizeof(link) - 1);
60cd4e3c3eSJouni Malinen 		if (len >= 0) {
61cd4e3c3eSJouni Malinen 			link[len] = '\0';
62cd4e3c3eSJouni Malinen 			if (strstr(link, DRIVER_NAME_60G))
63cd4e3c3eSJouni Malinen 				return DRIVER_WIL6210;
64cd4e3c3eSJouni Malinen 		}
65cd4e3c3eSJouni Malinen 
66cd4e3c3eSJouni Malinen 		if (stat("/sys/module/mac80211", &s) == 0)
67cd4e3c3eSJouni Malinen 			return DRIVER_MAC80211;
68cd4e3c3eSJouni Malinen 		return DRIVER_ATHEROS;
69cd4e3c3eSJouni Malinen 	}
70cd4e3c3eSJouni Malinen 	return wifi_chip_type;
71cd4e3c3eSJouni Malinen }
72cd4e3c3eSJouni Malinen 
73cd4e3c3eSJouni Malinen 
74cd4e3c3eSJouni Malinen enum openwrt_driver_type get_openwrt_driver_type(void)
75cd4e3c3eSJouni Malinen {
76cd4e3c3eSJouni Malinen 	struct stat s;
77cd4e3c3eSJouni Malinen 
78cd4e3c3eSJouni Malinen 	if (openwrt_chip_type == OPENWRT_DRIVER_NOT_SET) {
79a62e20abSSarvepalli, Rajesh Babu 		if (stat("/sys/module/umac", &s) == 0)
80cd4e3c3eSJouni Malinen 			openwrt_chip_type = OPENWRT_DRIVER_ATHEROS;
81cd4e3c3eSJouni Malinen 	}
82cd4e3c3eSJouni Malinen 
83cd4e3c3eSJouni Malinen 	return openwrt_chip_type;
84cd4e3c3eSJouni Malinen }
85cd4e3c3eSJouni Malinen 
86cd4e3c3eSJouni Malinen 
87cd4e3c3eSJouni Malinen enum sigma_program sigma_program_to_enum(const char *prog)
88cd4e3c3eSJouni Malinen {
89cd4e3c3eSJouni Malinen 	if (prog == NULL)
90cd4e3c3eSJouni Malinen 		return PROGRAM_UNKNOWN;
91cd4e3c3eSJouni Malinen 
92cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "TDLS") == 0)
93cd4e3c3eSJouni Malinen 		return PROGRAM_TDLS;
94cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "HS2") == 0)
95cd4e3c3eSJouni Malinen 		return PROGRAM_HS2;
96cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "HS2_R2") == 0 ||
97cd4e3c3eSJouni Malinen 	    strcasecmp(prog, "HS2-R2") == 0)
98cd4e3c3eSJouni Malinen 		return PROGRAM_HS2_R2;
99cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "WFD") == 0)
100cd4e3c3eSJouni Malinen 		return PROGRAM_WFD;
101659a34c4SAmarnath Hullur Subramanyam 	if (strcasecmp(prog, "DisplayR2") == 0)
102659a34c4SAmarnath Hullur Subramanyam 		return PROGRAM_DISPLAYR2;
103cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "PMF") == 0)
104cd4e3c3eSJouni Malinen 		return PROGRAM_PMF;
105cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "WPS") == 0)
106cd4e3c3eSJouni Malinen 		return PROGRAM_WPS;
107cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "11n") == 0)
108cd4e3c3eSJouni Malinen 		return PROGRAM_HT;
109cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "VHT") == 0)
110cd4e3c3eSJouni Malinen 		return PROGRAM_VHT;
111cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "60GHZ") == 0)
112cd4e3c3eSJouni Malinen 		return PROGRAM_60GHZ;
113cd4e3c3eSJouni Malinen 	if (strcasecmp(prog, "NAN") == 0)
114cd4e3c3eSJouni Malinen 		return PROGRAM_NAN;
11512dd4145Spriyadharshini gowthaman 	if (strcasecmp(prog, "LOC") == 0)
11612dd4145Spriyadharshini gowthaman 		return PROGRAM_LOC;
117b4e05fc1Spriyadharshini gowthaman 	if (strcasecmp(prog, "MBO") == 0)
118b4e05fc1Spriyadharshini gowthaman 		return PROGRAM_MBO;
11933ea287aSAdil Saeed Musthafa 	if (strcasecmp(prog, "IoTLP") == 0)
12033ea287aSAdil Saeed Musthafa 		return PROGRAM_IOTLP;
1215c3813a7SJouni Malinen 	if (strcasecmp(prog, "DPP") == 0)
1225c3813a7SJouni Malinen 		return PROGRAM_DPP;
123a2cb567bSAnkita Bajaj 	if (strcasecmp(prog, "OCE") == 0)
124a2cb567bSAnkita Bajaj 		return PROGRAM_OCE;
125*0e209fccSpriyadharshini gowthaman 	if (strcasecmp(prog, "WPA3") == 0)
126*0e209fccSpriyadharshini gowthaman 		return PROGRAM_WPA3;
127cd4e3c3eSJouni Malinen 
128cd4e3c3eSJouni Malinen 	return PROGRAM_UNKNOWN;
129cd4e3c3eSJouni Malinen }
13072462ef3Spriyadharshini gowthaman 
13172462ef3Spriyadharshini gowthaman 
13272462ef3Spriyadharshini gowthaman static int parse_hex(char c)
13372462ef3Spriyadharshini gowthaman {
13472462ef3Spriyadharshini gowthaman 	if (c >= '0' && c <= '9')
13572462ef3Spriyadharshini gowthaman 		return c - '0';
13672462ef3Spriyadharshini gowthaman 	if (c >= 'a' && c <= 'f')
13772462ef3Spriyadharshini gowthaman 		return c - 'a' + 10;
13872462ef3Spriyadharshini gowthaman 	if (c >= 'A' && c <= 'F')
13972462ef3Spriyadharshini gowthaman 		return c - 'A' + 10;
14072462ef3Spriyadharshini gowthaman 	return -1;
14172462ef3Spriyadharshini gowthaman }
14272462ef3Spriyadharshini gowthaman 
14372462ef3Spriyadharshini gowthaman 
14472462ef3Spriyadharshini gowthaman static int hex_byte(const char *str)
14572462ef3Spriyadharshini gowthaman {
14672462ef3Spriyadharshini gowthaman 	int res1, res2;
14772462ef3Spriyadharshini gowthaman 
14872462ef3Spriyadharshini gowthaman 	res1 = parse_hex(str[0]);
14972462ef3Spriyadharshini gowthaman 	if (res1 < 0)
15072462ef3Spriyadharshini gowthaman 		return -1;
15172462ef3Spriyadharshini gowthaman 	res2 = parse_hex(str[1]);
15272462ef3Spriyadharshini gowthaman 	if (res2 < 0)
15372462ef3Spriyadharshini gowthaman 		return -1;
15472462ef3Spriyadharshini gowthaman 	return (res1 << 4) | res2;
15572462ef3Spriyadharshini gowthaman }
15672462ef3Spriyadharshini gowthaman 
15772462ef3Spriyadharshini gowthaman 
15808cf231dSJouni Malinen int parse_hexstr(const char *hex, unsigned char *buf, size_t buflen)
15908cf231dSJouni Malinen {
16008cf231dSJouni Malinen 	size_t i;
16108cf231dSJouni Malinen 	const char *pos = hex;
16208cf231dSJouni Malinen 
16308cf231dSJouni Malinen 	for (i = 0; i < buflen; i++) {
16408cf231dSJouni Malinen 		int val;
16508cf231dSJouni Malinen 
16608cf231dSJouni Malinen 		if (*pos == '\0')
16708cf231dSJouni Malinen 			break;
16808cf231dSJouni Malinen 		val = hex_byte(pos);
16908cf231dSJouni Malinen 		if (val < 0)
17008cf231dSJouni Malinen 			return -1;
17108cf231dSJouni Malinen 		buf[i] = val;
17208cf231dSJouni Malinen 		pos += 2;
17308cf231dSJouni Malinen 	}
17408cf231dSJouni Malinen 
17508cf231dSJouni Malinen 	return i;
17608cf231dSJouni Malinen }
17708cf231dSJouni Malinen 
17808cf231dSJouni Malinen 
17972462ef3Spriyadharshini gowthaman int parse_mac_address(struct sigma_dut *dut, const char *arg,
18072462ef3Spriyadharshini gowthaman 		      unsigned char *addr)
18172462ef3Spriyadharshini gowthaman {
18272462ef3Spriyadharshini gowthaman 	int i;
18372462ef3Spriyadharshini gowthaman 	const char *pos = arg;
18472462ef3Spriyadharshini gowthaman 
18572462ef3Spriyadharshini gowthaman 	if (strlen(arg) != 17)
18672462ef3Spriyadharshini gowthaman 		goto fail;
18772462ef3Spriyadharshini gowthaman 
18872462ef3Spriyadharshini gowthaman 	for (i = 0; i < ETH_ALEN; i++) {
18972462ef3Spriyadharshini gowthaman 		int val;
19072462ef3Spriyadharshini gowthaman 
19172462ef3Spriyadharshini gowthaman 		val = hex_byte(pos);
19272462ef3Spriyadharshini gowthaman 		if (val < 0)
19372462ef3Spriyadharshini gowthaman 			goto fail;
19472462ef3Spriyadharshini gowthaman 		addr[i] = val;
19572462ef3Spriyadharshini gowthaman 		if (i + 1 < ETH_ALEN) {
19672462ef3Spriyadharshini gowthaman 			pos += 2;
19772462ef3Spriyadharshini gowthaman 			if (*pos != ':')
19872462ef3Spriyadharshini gowthaman 				goto fail;
19972462ef3Spriyadharshini gowthaman 			pos++;
20072462ef3Spriyadharshini gowthaman 		}
20172462ef3Spriyadharshini gowthaman 	}
20272462ef3Spriyadharshini gowthaman 
20372462ef3Spriyadharshini gowthaman 	return 0;
20472462ef3Spriyadharshini gowthaman 
20572462ef3Spriyadharshini gowthaman fail:
20672462ef3Spriyadharshini gowthaman 	sigma_dut_print(dut, DUT_MSG_ERROR,
20772462ef3Spriyadharshini gowthaman 			"Invalid MAC address %s (expected format xx:xx:xx:xx:xx:xx)",
20872462ef3Spriyadharshini gowthaman 			arg);
20972462ef3Spriyadharshini gowthaman 	return -1;
21072462ef3Spriyadharshini gowthaman }
2117192dc42SRakesh Sunki 
2127192dc42SRakesh Sunki 
2137192dc42SRakesh Sunki unsigned int channel_to_freq(unsigned int channel)
2147192dc42SRakesh Sunki {
2157192dc42SRakesh Sunki 	if (channel >= 1 && channel <= 13)
2167192dc42SRakesh Sunki 		return 2407 + 5 * channel;
2177192dc42SRakesh Sunki 	if (channel == 14)
2187192dc42SRakesh Sunki 		return 2484;
2197192dc42SRakesh Sunki 	if (channel >= 36 && channel <= 165)
2207192dc42SRakesh Sunki 		return 5000 + 5 * channel;
2217192dc42SRakesh Sunki 
2227192dc42SRakesh Sunki 	return 0;
2237192dc42SRakesh Sunki }
2247192dc42SRakesh Sunki 
2257192dc42SRakesh Sunki 
2267192dc42SRakesh Sunki unsigned int freq_to_channel(unsigned int freq)
2277192dc42SRakesh Sunki {
2287192dc42SRakesh Sunki 	if (freq >= 2412 && freq <= 2472)
2297192dc42SRakesh Sunki 		return (freq - 2407) / 5;
2307192dc42SRakesh Sunki 	if (freq == 2484)
2317192dc42SRakesh Sunki 		return 14;
2327192dc42SRakesh Sunki 	if (freq >= 5180 && freq <= 5825)
2337192dc42SRakesh Sunki 		return (freq - 5000) / 5;
2347192dc42SRakesh Sunki 	return 0;
2357192dc42SRakesh Sunki }
236769731a2SPeng Xu 
237769731a2SPeng Xu 
2388f8e74b5SRakesh Sunki void convert_mac_addr_to_ipv6_lladdr(u8 *mac_addr, char *ipv6_buf,
2398f8e74b5SRakesh Sunki 				     size_t buf_len)
2408f8e74b5SRakesh Sunki {
2418f8e74b5SRakesh Sunki 	u8 temp = mac_addr[0] ^ 0x02;
2428f8e74b5SRakesh Sunki 
2438f8e74b5SRakesh Sunki 	snprintf(ipv6_buf, buf_len, "fe80::%02x%02x:%02xff:fe%02x:%02x%02x",
2448f8e74b5SRakesh Sunki 		 temp, mac_addr[1], mac_addr[2],
2458f8e74b5SRakesh Sunki 		 mac_addr[3], mac_addr[4], mac_addr[5]);
2468f8e74b5SRakesh Sunki }
2478f8e74b5SRakesh Sunki 
2488f8e74b5SRakesh Sunki 
249769731a2SPeng Xu #ifndef ANDROID
250769731a2SPeng Xu 
251769731a2SPeng Xu size_t strlcpy(char *dest, const char *src, size_t siz)
252769731a2SPeng Xu {
253769731a2SPeng Xu 	const char *s = src;
254769731a2SPeng Xu 	size_t left = siz;
255769731a2SPeng Xu 
256769731a2SPeng Xu 	if (left) {
257769731a2SPeng Xu 		/* Copy string up to the maximum size of the dest buffer */
258769731a2SPeng Xu 		while (--left != 0) {
259769731a2SPeng Xu 			if ((*dest++ = *s++) == '\0')
260769731a2SPeng Xu 				break;
261769731a2SPeng Xu 		}
262769731a2SPeng Xu 	}
263769731a2SPeng Xu 
264769731a2SPeng Xu 	if (left == 0) {
265769731a2SPeng Xu 		/* Not enough room for the string; force NUL-termination */
266769731a2SPeng Xu 		if (siz != 0)
267769731a2SPeng Xu 			*dest = '\0';
268769731a2SPeng Xu 		while (*s++)
269769731a2SPeng Xu 			; /* determine total src string length */
270769731a2SPeng Xu 	}
271769731a2SPeng Xu 
272769731a2SPeng Xu 	return s - src - 1;
273769731a2SPeng Xu }
274769731a2SPeng Xu 
275769731a2SPeng Xu 
276769731a2SPeng Xu size_t strlcat(char *dst, const char *str, size_t size)
277769731a2SPeng Xu {
278769731a2SPeng Xu 	char *pos;
279769731a2SPeng Xu 	size_t dstlen, srclen, copy;
280769731a2SPeng Xu 
281769731a2SPeng Xu 	srclen = strlen(str);
282769731a2SPeng Xu 	for (pos = dst; pos - dst < size && *dst; pos++)
283769731a2SPeng Xu 		;
284769731a2SPeng Xu 	dstlen = pos - dst;
285769731a2SPeng Xu 	if (*dst)
286769731a2SPeng Xu 		return dstlen + srclen;
287769731a2SPeng Xu 	if (dstlen + srclen + 1 > size)
288769731a2SPeng Xu 		copy = size - dstlen - 1;
289769731a2SPeng Xu 	else
290769731a2SPeng Xu 		copy = srclen;
291769731a2SPeng Xu 	memcpy(pos, str, copy);
292769731a2SPeng Xu 	pos[copy] = '\0';
293769731a2SPeng Xu 	return dstlen + srclen;
294769731a2SPeng Xu }
295769731a2SPeng Xu 
296769731a2SPeng Xu #endif /* ANDROID */
2971bde7947SAnkita Bajaj 
2981bde7947SAnkita Bajaj 
2991bde7947SAnkita Bajaj void hex_dump(struct sigma_dut *dut, u8 *data, size_t len)
3001bde7947SAnkita Bajaj {
3011bde7947SAnkita Bajaj 	char buf[1024];
3021bde7947SAnkita Bajaj 	size_t index;
3031bde7947SAnkita Bajaj 	u8 *ptr;
3041bde7947SAnkita Bajaj 	int pos;
3051bde7947SAnkita Bajaj 
3061bde7947SAnkita Bajaj 	memset(buf, 0, sizeof(buf));
3071bde7947SAnkita Bajaj 	ptr = data;
3081bde7947SAnkita Bajaj 	pos = 0;
3091bde7947SAnkita Bajaj 	for (index = 0; index < len; index++) {
3101bde7947SAnkita Bajaj 		pos += snprintf(&(buf[pos]), sizeof(buf) - pos,
3111bde7947SAnkita Bajaj 				"%02x ", *ptr++);
3121bde7947SAnkita Bajaj 		if (pos > 1020)
3131bde7947SAnkita Bajaj 			break;
3141bde7947SAnkita Bajaj 	}
3151bde7947SAnkita Bajaj 	sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len);
3161bde7947SAnkita Bajaj 	sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf);
3171bde7947SAnkita Bajaj }
318