xref: /wlan-dirver/utils/sigma-dut/utils.c (revision f0f8805aa32da5a7803079812d520cc99bf02da7)
1 /*
2  * Sigma Control API DUT (station/AP)
3  * Copyright (c) 2014-2017, Qualcomm Atheros, Inc.
4  * Copyright (c) 2018, The Linux Foundation
5  * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
6  * All Rights Reserved.
7  * Licensed under the Clear BSD license. See README for more details.
8  */
9 
10 #include "sigma_dut.h"
11 #include <sys/ioctl.h>
12 #include <sys/stat.h>
13 #include "wpa_helpers.h"
14 
15 enum driver_type wifi_chip_type = DRIVER_NOT_SET;
16 enum openwrt_driver_type openwrt_chip_type = OPENWRT_DRIVER_NOT_SET;
17 
18 struct wcn_drv_priv_cmd {
19 	char *buf;
20 	int used_len;
21 	int total_len;
22 };
23 
file_exists(const char * fname)24 int file_exists(const char *fname)
25 {
26 	struct stat s;
27 	return stat(fname, &s) == 0;
28 }
29 
30 
set_wifi_chip(const char * chip_type)31 int set_wifi_chip(const char *chip_type)
32 {
33 	if (!strncmp(chip_type, "WCN", strlen("WCN")))
34 		wifi_chip_type = DRIVER_WCN;
35 	else if (!strncmp(chip_type, "ATHEROS", strlen("ATHEROS")))
36 		wifi_chip_type = DRIVER_ATHEROS;
37 	else if (!strncmp(chip_type, "AR6003", strlen("AR6003")))
38 		wifi_chip_type = DRIVER_AR6003;
39 	else if (strcmp(chip_type, "MAC80211") == 0)
40 		wifi_chip_type = DRIVER_MAC80211;
41 	else if (strcmp(chip_type, "QNXNTO") == 0)
42 		wifi_chip_type = DRIVER_QNXNTO;
43 	else if (strcmp(chip_type, "OPENWRT") == 0)
44 		wifi_chip_type = DRIVER_OPENWRT;
45 	else if (!strncmp(chip_type, "LINUX-WCN", strlen("LINUX-WCN")))
46 		wifi_chip_type = DRIVER_LINUX_WCN;
47 	else
48 		return -1;
49 
50 	return 0;
51 }
52 
53 
get_driver_type(struct sigma_dut * dut)54 enum driver_type get_driver_type(struct sigma_dut *dut)
55 {
56 	struct stat s;
57 	if (wifi_chip_type == DRIVER_NOT_SET) {
58 		/* Check for 60G driver */
59 		ssize_t len;
60 		char link[256];
61 		char buf[256];
62 		const char *ifname = get_station_ifname(dut);
63 
64 		snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver",
65 			 ifname);
66 		len = readlink(buf, link, sizeof(link) - 1);
67 		if (len >= 0) {
68 			link[len] = '\0';
69 			if (strstr(link, DRIVER_NAME_60G))
70 				return DRIVER_WIL6210;
71 		}
72 
73 		if (stat("/sys/module/mac80211", &s) == 0)
74 			return DRIVER_MAC80211;
75 		return DRIVER_ATHEROS;
76 	}
77 	return wifi_chip_type;
78 }
79 
80 
sigma_dut_get_device_driver_name(const char * ifname,char * name,size_t size)81 void sigma_dut_get_device_driver_name(const char *ifname, char *name,
82 				      size_t size)
83 {
84 	char fname[128], path[128];
85 	struct stat s;
86 	ssize_t res;
87 	char *pos;
88 
89 	name[0] = '\0';
90 
91 	snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname);
92 	if (stat(path, &s) != 0)
93 		return;
94 
95 	res = snprintf(fname, sizeof(fname),
96 		       "/sys/class/net/%s/device/driver", ifname);
97 	if (res < 0 || res >= sizeof(fname))
98 		return;
99 	res = readlink(fname, path, sizeof(path));
100 	if (res < 0)
101 		return;
102 
103 	if (res >= (int) sizeof(path))
104 		res = sizeof(path) - 1;
105 	path[res] = '\0';
106 	pos = strrchr(path, '/');
107 	if (!pos)
108 		pos = path;
109 	else
110 		pos++;
111 	snprintf(name, size, "%s", pos);
112 }
113 
114 
get_openwrt_driver_type(void)115 enum openwrt_driver_type get_openwrt_driver_type(void)
116 {
117 	struct stat s;
118 
119 	if (openwrt_chip_type == OPENWRT_DRIVER_NOT_SET) {
120 		if (stat("/sys/module/umac", &s) == 0 ||
121 		    stat("/sys/module/atd", &s) == 0)
122 			openwrt_chip_type = OPENWRT_DRIVER_ATHEROS;
123 	}
124 
125 	return openwrt_chip_type;
126 }
127 
128 
sigma_program_to_enum(const char * prog)129 enum sigma_program sigma_program_to_enum(const char *prog)
130 {
131 	if (prog == NULL)
132 		return PROGRAM_UNKNOWN;
133 
134 	if (strcasecmp(prog, "TDLS") == 0)
135 		return PROGRAM_TDLS;
136 	if (strcasecmp(prog, "HS2") == 0)
137 		return PROGRAM_HS2;
138 	if (strcasecmp(prog, "HS2_R2") == 0 ||
139 	    strcasecmp(prog, "HS2-R2") == 0)
140 		return PROGRAM_HS2_R2;
141 	if (strcasecmp(prog, "HS2-R3") == 0)
142 		return PROGRAM_HS2_R3;
143 	if (strcasecmp(prog, "WFD") == 0)
144 		return PROGRAM_WFD;
145 	if (strcasecmp(prog, "DisplayR2") == 0)
146 		return PROGRAM_DISPLAYR2;
147 	if (strcasecmp(prog, "PMF") == 0)
148 		return PROGRAM_PMF;
149 	if (strcasecmp(prog, "WPS") == 0)
150 		return PROGRAM_WPS;
151 	if (strcasecmp(prog, "11n") == 0)
152 		return PROGRAM_HT;
153 	if (strcasecmp(prog, "VHT") == 0)
154 		return PROGRAM_VHT;
155 	if (strcasecmp(prog, "60GHZ") == 0)
156 		return PROGRAM_60GHZ;
157 	if (strcasecmp(prog, "NAN") == 0)
158 		return PROGRAM_NAN;
159 	if (strcasecmp(prog, "LOC") == 0)
160 		return PROGRAM_LOC;
161 	if (strcasecmp(prog, "MBO") == 0)
162 		return PROGRAM_MBO;
163 	if (strcasecmp(prog, "IoTLP") == 0)
164 		return PROGRAM_IOTLP;
165 	if (strcasecmp(prog, "DPP") == 0)
166 		return PROGRAM_DPP;
167 	if (strcasecmp(prog, "OCE") == 0)
168 		return PROGRAM_OCE;
169 	if (strcasecmp(prog, "WPA3") == 0)
170 		return PROGRAM_WPA3;
171 	if (strcasecmp(prog, "HE") == 0)
172 		return PROGRAM_HE;
173 	if (strcasecmp(prog, "QM") == 0)
174 		return PROGRAM_QM;
175 
176 	return PROGRAM_UNKNOWN;
177 }
178 
179 
parse_hex(char c)180 static int parse_hex(char c)
181 {
182 	if (c >= '0' && c <= '9')
183 		return c - '0';
184 	if (c >= 'a' && c <= 'f')
185 		return c - 'a' + 10;
186 	if (c >= 'A' && c <= 'F')
187 		return c - 'A' + 10;
188 	return -1;
189 }
190 
191 
hex_byte(const char * str)192 int hex_byte(const char *str)
193 {
194 	int res1, res2;
195 
196 	res1 = parse_hex(str[0]);
197 	if (res1 < 0)
198 		return -1;
199 	res2 = parse_hex(str[1]);
200 	if (res2 < 0)
201 		return -1;
202 	return (res1 << 4) | res2;
203 }
204 
205 
parse_hexstr(const char * hex,unsigned char * buf,size_t buflen)206 int parse_hexstr(const char *hex, unsigned char *buf, size_t buflen)
207 {
208 	size_t i;
209 	const char *pos = hex;
210 
211 	for (i = 0; i < buflen; i++) {
212 		int val;
213 
214 		if (*pos == '\0')
215 			break;
216 		val = hex_byte(pos);
217 		if (val < 0)
218 			return -1;
219 		buf[i] = val;
220 		pos += 2;
221 	}
222 
223 	return i;
224 }
225 
226 
parse_mac_address(struct sigma_dut * dut,const char * arg,unsigned char * addr)227 int parse_mac_address(struct sigma_dut *dut, const char *arg,
228 		      unsigned char *addr)
229 {
230 	int i;
231 	const char *pos = arg;
232 
233 	if (strlen(arg) != 17)
234 		goto fail;
235 
236 	for (i = 0; i < ETH_ALEN; i++) {
237 		int val;
238 
239 		val = hex_byte(pos);
240 		if (val < 0)
241 			goto fail;
242 		addr[i] = val;
243 		if (i + 1 < ETH_ALEN) {
244 			pos += 2;
245 			if (*pos != ':')
246 				goto fail;
247 			pos++;
248 		}
249 	}
250 
251 	return 0;
252 
253 fail:
254 	sigma_dut_print(dut, DUT_MSG_ERROR,
255 			"Invalid MAC address %s (expected format xx:xx:xx:xx:xx:xx)",
256 			arg);
257 	return -1;
258 }
259 
260 
is_60g_sigma_dut(struct sigma_dut * dut)261 int is_60g_sigma_dut(struct sigma_dut *dut)
262 {
263 	return dut->program == PROGRAM_60GHZ ||
264 		(dut->program == PROGRAM_WPS &&
265 		 (get_driver_type(dut) == DRIVER_WIL6210));
266 }
267 
268 
channel_to_freq(struct sigma_dut * dut,unsigned int channel)269 unsigned int channel_to_freq(struct sigma_dut *dut, unsigned int channel)
270 {
271 	if (is_60g_sigma_dut(dut)) {
272 		if (channel >= 1 && channel <= 4)
273 			return 58320 + 2160 * channel;
274 
275 		return 0;
276 	}
277 
278 	if (channel >= 1 && channel <= 13)
279 		return 2407 + 5 * channel;
280 	if (channel == 14)
281 		return 2484;
282 	if (channel >= 36 && channel <= 165)
283 		return 5000 + 5 * channel;
284 
285 	return 0;
286 }
287 
288 
freq_to_channel(unsigned int freq)289 unsigned int freq_to_channel(unsigned int freq)
290 {
291 	if (freq >= 2412 && freq <= 2472)
292 		return (freq - 2407) / 5;
293 	if (freq == 2484)
294 		return 14;
295 	if (freq >= 5180 && freq <= 5825)
296 		return (freq - 5000) / 5;
297 	if (freq >= 58320 && freq <= 64800)
298 		return (freq - 58320) / 2160;
299 	return 0;
300 }
301 
302 
is_ipv6_addr(const char * str)303 int is_ipv6_addr(const char *str)
304 {
305 	struct sockaddr_in6 addr;
306 
307 	return inet_pton(AF_INET6, str, &(addr.sin6_addr));
308 }
309 
310 
convert_mac_addr_to_ipv6_lladdr(u8 * mac_addr,char * ipv6_buf,size_t buf_len)311 void convert_mac_addr_to_ipv6_lladdr(u8 *mac_addr, char *ipv6_buf,
312 				     size_t buf_len)
313 {
314 	u8 temp = mac_addr[0] ^ 0x02;
315 
316 	snprintf(ipv6_buf, buf_len, "fe80::%02x%02x:%02xff:fe%02x:%02x%02x",
317 		 temp, mac_addr[1], mac_addr[2],
318 		 mac_addr[3], mac_addr[4], mac_addr[5]);
319 }
320 
321 
convert_mac_addr_to_ipv6_linklocal(const u8 * mac_addr,u8 * ipv6)322 size_t convert_mac_addr_to_ipv6_linklocal(const u8 *mac_addr, u8 *ipv6)
323 {
324 	int i;
325 
326 	ipv6[0] = 0xfe;
327 	ipv6[1] = 0x80;
328 	for (i = 2; i < 8; i++)
329 		ipv6[i] = 0;
330 	ipv6[8] = mac_addr[0] ^ 0x02;
331 	ipv6[9] = mac_addr[1];
332 	ipv6[10] = mac_addr[2];
333 	ipv6[11] = 0xff;
334 	ipv6[12] = 0xfe;
335 	ipv6[13] = mac_addr[3];
336 	ipv6[14] = mac_addr[4];
337 	ipv6[15] = mac_addr[5];
338 
339 	return 16;
340 }
341 
342 
343 #ifndef ANDROID
344 
strlcpy(char * dest,const char * src,size_t siz)345 size_t strlcpy(char *dest, const char *src, size_t siz)
346 {
347 	const char *s = src;
348 	size_t left = siz;
349 
350 	if (left) {
351 		/* Copy string up to the maximum size of the dest buffer */
352 		while (--left != 0) {
353 			if ((*dest++ = *s++) == '\0')
354 				break;
355 		}
356 	}
357 
358 	if (left == 0) {
359 		/* Not enough room for the string; force NUL-termination */
360 		if (siz != 0)
361 			*dest = '\0';
362 		while (*s++)
363 			; /* determine total src string length */
364 	}
365 
366 	return s - src - 1;
367 }
368 
369 
strlcat(char * dst,const char * str,size_t size)370 size_t strlcat(char *dst, const char *str, size_t size)
371 {
372 	char *pos;
373 	size_t dstlen, srclen, copy;
374 
375 	srclen = strlen(str);
376 	for (pos = dst; pos - dst < size && *dst; pos++)
377 		;
378 	dstlen = pos - dst;
379 	if (*dst)
380 		return dstlen + srclen;
381 	if (dstlen + srclen + 1 > size)
382 		copy = size - dstlen - 1;
383 	else
384 		copy = srclen;
385 	memcpy(pos, str, copy);
386 	pos[copy] = '\0';
387 	return dstlen + srclen;
388 }
389 
390 #endif /* ANDROID */
391 
392 
hex_dump(struct sigma_dut * dut,u8 * data,size_t len)393 void hex_dump(struct sigma_dut *dut, u8 *data, size_t len)
394 {
395 	char buf[1024];
396 	size_t index;
397 	u8 *ptr;
398 	int pos;
399 
400 	memset(buf, 0, sizeof(buf));
401 	ptr = data;
402 	pos = 0;
403 	for (index = 0; index < len; index++) {
404 		pos += snprintf(&(buf[pos]), sizeof(buf) - pos,
405 				"%02x ", *ptr++);
406 		if (pos > 1020)
407 			break;
408 	}
409 	sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len);
410 	sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf);
411 }
412 
413 
414 #ifdef NL80211_SUPPORT
415 
nl80211_cmd(struct sigma_dut * dut,struct nl80211_ctx * ctx,struct nl_msg * msg,int flags,uint8_t cmd)416 void * nl80211_cmd(struct sigma_dut *dut, struct nl80211_ctx *ctx,
417 		   struct nl_msg *msg, int flags, uint8_t cmd)
418 {
419 	return genlmsg_put(msg, 0, 0, ctx->netlink_familyid,
420 			   0, flags, cmd, 0);
421 }
422 
423 
424 static struct nl_msg *
nl80211_ifindex_msg(struct sigma_dut * dut,struct nl80211_ctx * ctx,int ifindex,int flags,uint8_t cmd)425 nl80211_ifindex_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx, int ifindex,
426 		    int flags, uint8_t cmd)
427 {
428 	struct nl_msg *msg;
429 
430 	msg = nlmsg_alloc();
431 	if (!msg) {
432 		sigma_dut_print(dut, DUT_MSG_ERROR,
433 				"Failed to allocate NL message");
434 		return NULL;
435 	}
436 
437 	if (!nl80211_cmd(dut, ctx, msg, flags, cmd) ||
438 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
439 		nlmsg_free(msg);
440 		return NULL;
441 	}
442 
443 	return msg;
444 }
445 
446 
nl80211_drv_msg(struct sigma_dut * dut,struct nl80211_ctx * ctx,int ifindex,int flags,uint8_t cmd)447 struct nl_msg * nl80211_drv_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx,
448 				int ifindex, int flags, uint8_t cmd)
449 {
450 	return nl80211_ifindex_msg(dut, ctx, ifindex, flags, cmd);
451 }
452 
453 
ack_handler(struct nl_msg * msg,void * arg)454 static int ack_handler(struct nl_msg *msg, void *arg)
455 {
456 	int *err = arg;
457 	*err = 0;
458 	return NL_STOP;
459 }
460 
461 
finish_handler(struct nl_msg * msg,void * arg)462 static int finish_handler(struct nl_msg *msg, void *arg)
463 {
464 	int *ret = arg;
465 	*ret = 0;
466 	return NL_SKIP;
467 }
468 
469 
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)470 static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
471 			 void *arg)
472 {
473 	int *ret = arg;
474 	*ret = err->error;
475 	return NL_SKIP;
476 }
477 
478 
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)479 int send_and_recv_msgs(struct sigma_dut *dut, struct nl80211_ctx *ctx,
480 		       struct nl_msg *nlmsg,
481 		       int (*valid_handler)(struct nl_msg *, void *),
482 		       void *valid_data)
483 {
484 	struct nl_cb *cb;
485 	int err = -ENOMEM;
486 
487 	if (!nlmsg)
488 		return -ENOMEM;
489 
490 	cb = nl_cb_alloc(NL_CB_DEFAULT);
491 	if (!cb)
492 		goto out;
493 
494 	err = nl_send_auto_complete(ctx->sock, nlmsg);
495 	if (err < 0) {
496 		sigma_dut_print(dut, DUT_MSG_ERROR,
497 				"nl80211: failed to send err=%d", err);
498 		goto out;
499 	}
500 
501 	err = 1;
502 
503 	nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
504 	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
505 	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
506 
507 	if (valid_handler)
508 		nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
509 			  valid_handler, valid_data);
510 
511 	while (err > 0) {
512 		int res = nl_recvmsgs(ctx->sock, cb);
513 
514 		if (res < 0) {
515 			sigma_dut_print(dut, DUT_MSG_ERROR,
516 					"nl80211: %s->nl_recvmsgs failed: res=%d, err=%d",
517 					__func__, res, err);
518 		}
519 	}
520  out:
521 	nl_cb_put(cb);
522 	if (!valid_handler && valid_data == (void *) -1) {
523 		if (nlmsg) {
524 			struct nlmsghdr *hdr = nlmsg_hdr(nlmsg);
525 			void *data = nlmsg_data(hdr);
526 			int len = hdr->nlmsg_len - NLMSG_HDRLEN;
527 
528 			memset(data, 0, len);
529 		}
530 	}
531 
532 	nlmsg_free(nlmsg);
533 	return err;
534 }
535 
536 
nl80211_init(struct sigma_dut * dut)537 struct nl80211_ctx * nl80211_init(struct sigma_dut *dut)
538 {
539 	struct nl80211_ctx *ctx;
540 
541 	ctx = calloc(1, sizeof(struct nl80211_ctx));
542 	if (!ctx) {
543 		sigma_dut_print(dut, DUT_MSG_ERROR,
544 				"Failed to alloc nl80211_ctx");
545 		return NULL;
546 	}
547 
548 	ctx->sock = nl_socket_alloc();
549 	if (!ctx->sock) {
550 		sigma_dut_print(dut, DUT_MSG_ERROR,
551 				"Failed to create NL socket, err: %s",
552 				strerror(errno));
553 		goto cleanup;
554 	}
555 
556 	if (nl_connect(ctx->sock, NETLINK_GENERIC)) {
557 		sigma_dut_print(dut, DUT_MSG_ERROR,
558 				"Could not connect socket, err: %s",
559 				strerror(errno));
560 		goto cleanup;
561 	}
562 
563 	if (nl_socket_set_buffer_size(ctx->sock, SOCK_BUF_SIZE, 0) < 0) {
564 		sigma_dut_print(dut, DUT_MSG_INFO,
565 				"Could not set nl_socket RX buffer size for sock: %s",
566 				strerror(errno));
567 	}
568 
569 	ctx->netlink_familyid = genl_ctrl_resolve(ctx->sock, "nl80211");
570 	if (ctx->netlink_familyid < 0) {
571 		sigma_dut_print(dut, DUT_MSG_ERROR,
572 				"Could not resolve nl80211 family id");
573 		goto cleanup;
574 	}
575 
576 	ctx->nlctrl_familyid = genl_ctrl_resolve(ctx->sock, "nlctrl");
577 	if (ctx->nlctrl_familyid < 0) {
578 		sigma_dut_print(dut, DUT_MSG_ERROR,
579 				"net link family nlctrl is not present: %d err:%s",
580 				ctx->nlctrl_familyid, strerror(errno));
581 		goto cleanup;
582 	}
583 
584 	return ctx;
585 
586 cleanup:
587 	if (ctx->sock)
588 		nl_socket_free(ctx->sock);
589 
590 	free(ctx);
591 	return NULL;
592 }
593 
594 
nl80211_deinit(struct sigma_dut * dut,struct nl80211_ctx * ctx)595 void nl80211_deinit(struct sigma_dut *dut, struct nl80211_ctx *ctx)
596 {
597 	if (!ctx || !ctx->sock) {
598 		sigma_dut_print(dut, DUT_MSG_ERROR, "%s: ctx/sock is NULL",
599 				__func__);
600 		return;
601 	}
602 	nl_socket_free(ctx->sock);
603 	free(ctx);
604 }
605 
606 
607 static struct nl_msg *
wcn_create_wifi_test_config_msg(struct sigma_dut * dut,const char * intf)608 wcn_create_wifi_test_config_msg(struct sigma_dut *dut, const char *intf)
609 {
610 	int ifindex;
611 	struct nl_msg *msg;
612 
613 	ifindex = if_nametoindex(intf);
614 	if (ifindex == 0) {
615 		sigma_dut_print(dut, DUT_MSG_ERROR,
616 				"%s: Index for interface %s failed",
617 				__func__, intf);
618 		return NULL;
619 	}
620 
621 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
622 				    NL80211_CMD_VENDOR)) ||
623 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
624 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
625 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
626 			QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION)) {
627 		nlmsg_free(msg);
628 		return NULL;
629 	}
630 
631 	return msg;
632 }
633 
634 
wcn_send_wifi_test_config_msg(struct sigma_dut * dut,struct nl_msg * msg,struct nlattr * params,int attr_id)635 static int wcn_send_wifi_test_config_msg(struct sigma_dut *dut,
636 					 struct nl_msg *msg,
637 					 struct nlattr *params, int attr_id)
638 {
639 	int ret;
640 
641 	nla_nest_end(msg, params);
642 
643 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
644 	if (ret) {
645 		sigma_dut_print(dut, DUT_MSG_ERROR,
646 				"%s: err in send_and_recv_msgs, ret=%d for %d",
647 				__func__, ret, attr_id);
648 	}
649 
650 	return ret;
651 }
652 
653 
wcn_wifi_test_config_set_flag(struct sigma_dut * dut,const char * intf,int attr_id)654 int wcn_wifi_test_config_set_flag(struct sigma_dut *dut, const char *intf,
655 				  int attr_id)
656 {
657 	struct nl_msg *msg;
658 	struct nlattr *params;
659 
660 	if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
661 	    !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
662 	    nla_put_flag(msg, attr_id)) {
663 		sigma_dut_print(dut, DUT_MSG_ERROR,
664 				"%s: err in adding test config data for %d",
665 				__func__, attr_id);
666 		nlmsg_free(msg);
667 		return -1;
668 	}
669 
670 	return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
671 }
672 
673 
wcn_wifi_test_config_set_u8(struct sigma_dut * dut,const char * intf,int attr_id,uint8_t val)674 int wcn_wifi_test_config_set_u8(struct sigma_dut *dut, const char *intf,
675 				int attr_id, uint8_t val)
676 {
677 	struct nl_msg *msg;
678 	struct nlattr *params;
679 
680 	if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
681 	    !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
682 	    nla_put_u8(msg, attr_id, val)) {
683 		sigma_dut_print(dut, DUT_MSG_ERROR,
684 				"%s: err in adding test config data for %d",
685 				__func__, attr_id);
686 		nlmsg_free(msg);
687 		return -1;
688 	}
689 
690 	return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
691 }
692 
693 
wcn_wifi_test_config_set_u16(struct sigma_dut * dut,const char * intf,int attr_id,uint16_t val)694 int wcn_wifi_test_config_set_u16(struct sigma_dut *dut, const char *intf,
695 				 int attr_id, uint16_t val)
696 {
697 	struct nl_msg *msg;
698 	struct nlattr *params;
699 
700 	if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
701 	    !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
702 	    nla_put_u16(msg, attr_id, val)) {
703 		sigma_dut_print(dut, DUT_MSG_ERROR,
704 				"%s: err in adding test config data for %d",
705 				__func__, attr_id);
706 		nlmsg_free(msg);
707 		return -1;
708 	}
709 
710 	return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
711 }
712 
713 #endif /* NL80211_SUPPORT */
714 
715 
get_wps_pin_checksum(int pin)716 static int get_wps_pin_checksum(int pin)
717 {
718 	int a = 0;
719 
720 	while (pin > 0) {
721 		a += 3 * (pin % 10);
722 		pin = pin / 10;
723 		a += (pin % 10);
724 		pin = pin / 10;
725 	}
726 
727 	return (10 - (a % 10)) % 10;
728 }
729 
730 
get_wps_pin_from_mac(struct sigma_dut * dut,const char * macaddr,char * pin,size_t len)731 int get_wps_pin_from_mac(struct sigma_dut *dut, const char *macaddr,
732 			 char *pin, size_t len)
733 {
734 	unsigned char mac[ETH_ALEN];
735 	int tmp, checksum;
736 
737 	if (len < 9)
738 		return -1;
739 	if (parse_mac_address(dut, macaddr, mac))
740 		return -1;
741 
742 	/*
743 	 * get 7 digit PIN from the last 24 bits of MAC
744 	 * range 1000000 - 9999999
745 	 */
746 	tmp = (mac[5] & 0xFF) | ((mac[4] & 0xFF) << 8) |
747 	      ((mac[3] & 0xFF) << 16);
748 	tmp = (tmp % 9000000) + 1000000;
749 	checksum = get_wps_pin_checksum(tmp);
750 	snprintf(pin, len, "%07d%01d", tmp, checksum);
751 	return 0;
752 }
753 
754 
get_wps_forced_version(struct sigma_dut * dut,const char * str)755 int get_wps_forced_version(struct sigma_dut *dut, const char *str)
756 {
757 	int major, minor, result = 0;
758 	int count = sscanf(str, "%d.%d", &major, &minor);
759 
760 	if (count == 2) {
761 		result = major * 16 + minor;
762 		sigma_dut_print(dut, DUT_MSG_DEBUG,
763 				"Force WPS version to 0x%02x (%s)",
764 				result, str);
765 	} else {
766 		sigma_dut_print(dut, DUT_MSG_ERROR,
767 				"Invalid WPS version %s", str);
768 	}
769 
770 	return result;
771 }
772 
773 
str_remove_chars(char * str,char ch)774 void str_remove_chars(char *str, char ch)
775 {
776 	char *pr = str, *pw = str;
777 
778 	while (*pr) {
779 		*pw = *pr++;
780 		if (*pw != ch)
781 			pw++;
782 	}
783 	*pw = '\0';
784 }
785 
786 
787 static const char base64_table[65] =
788 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
789 
790 
base64_encode(const char * src,size_t len,char * out,size_t out_len)791 int base64_encode(const char *src, size_t len, char *out, size_t out_len)
792 {
793 	unsigned char *pos;
794 	const unsigned char *end, *in;
795 	size_t olen;
796 
797 	olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
798 	olen++; /* nul termination */
799 	if (olen < len || olen > out_len)
800 		return -1;
801 
802 	end = (unsigned char *)(src + len);
803 	in = (unsigned char *)src;
804 	pos = (unsigned char *)out;
805 	while (end - in >= 3) {
806 		*pos++ = base64_table[(in[0] >> 2) & 0x3f];
807 		*pos++ = base64_table[(((in[0] & 0x03) << 4) |
808 				       (in[1] >> 4)) & 0x3f];
809 		*pos++ = base64_table[(((in[1] & 0x0f) << 2) |
810 				       (in[2] >> 6)) & 0x3f];
811 		*pos++ = base64_table[in[2] & 0x3f];
812 		in += 3;
813 	}
814 
815 	if (end - in) {
816 		*pos++ = base64_table[(in[0] >> 2) & 0x3f];
817 		if (end - in == 1) {
818 			*pos++ = base64_table[((in[0] & 0x03) << 4) & 0x3f];
819 			*pos++ = '=';
820 		} else {
821 			*pos++ = base64_table[(((in[0] & 0x03) << 4) |
822 					       (in[1] >> 4)) & 0x3f];
823 			*pos++ = base64_table[((in[1] & 0x0f) << 2) & 0x3f];
824 		}
825 		*pos++ = '=';
826 	}
827 
828 	*pos = '\0';
829 	return 0;
830 }
831 
832 
random_get_bytes(char * buf,size_t len)833 int random_get_bytes(char *buf, size_t len)
834 {
835 	FILE *f;
836 	size_t rc;
837 
838 	f = fopen("/dev/urandom", "rb");
839 	if (!f)
840 		return -1;
841 
842 	rc = fread(buf, 1, len, f);
843 	fclose(f);
844 
845 	return rc != len ? -1 : 0;
846 }
847 
848 
get_enable_disable(const char * val)849 int get_enable_disable(const char *val)
850 {
851 	if (strcasecmp(val, "enable") == 0 ||
852 	    strcasecmp(val, "enabled") == 0 ||
853 	    strcasecmp(val, "on") == 0 ||
854 	    strcasecmp(val, "yes") == 0)
855 		return 1;
856 	return atoi(val);
857 }
858 
859 
wcn_driver_cmd(const char * ifname,char * buf)860 int wcn_driver_cmd(const char *ifname, char *buf)
861 {
862 	int s, res;
863 	size_t buf_len;
864 	struct wcn_drv_priv_cmd priv_cmd;
865 	struct ifreq ifr;
866 
867 	s = socket(PF_INET, SOCK_DGRAM, 0);
868 	if (s < 0) {
869 		perror("socket");
870 		return -1;
871 	}
872 
873 	memset(&ifr, 0, sizeof(ifr));
874 	memset(&priv_cmd, 0, sizeof(priv_cmd));
875 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
876 	buf_len = strlen(buf);
877 	priv_cmd.buf = buf;
878 	priv_cmd.used_len = buf_len;
879 	priv_cmd.total_len = buf_len;
880 	ifr.ifr_data = (void *) &priv_cmd;
881 	res = ioctl(s, SIOCDEVPRIVATE + 1, &ifr);
882 	close(s);
883 	return res;
884 }
885 
886 
set_ipv6_addr(struct sigma_dut * dut,const char * ip,const char * mask,const char * ifname)887 int set_ipv6_addr(struct sigma_dut *dut, const char *ip, const char *mask,
888 		  const char *ifname)
889 {
890 	char buf[200];
891 
892 	snprintf(buf, sizeof(buf), "ip -6 addr del %s/%s dev %s", ip, mask,
893 		 ifname);
894 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
895 	if (system(buf) != 0) {
896 		/*
897 		 * This command may fail if the address being deleted does not
898 		 * exist. Inaction here is intentional.
899 		 */
900 	}
901 
902 	snprintf(buf, sizeof(buf), "ip -6 addr add %s/%s dev %s", ip, mask,
903 		 ifname);
904 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
905 	if (system(buf) != 0)
906 		return -1;
907 
908 	return 0;
909 }
910