blob: 1fa758605ca764f0d1894bdfd71ce762d748e9aa [file] [log] [blame]
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001/*
2 * Sigma Control API DUT (station/AP)
Amarnath Hullur Subramanyam659a34c2017-03-17 00:04:41 -07003 * Copyright (c) 2014-2017, Qualcomm Atheros, Inc.
Ankita Bajaj1bde7942018-01-09 19:15:01 +05304 * Copyright (c) 2018, The Linux Foundation
Alexei Avshalom Lazara37dc162019-02-04 14:06:48 +02005 * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006 * All Rights Reserved.
7 * Licensed under the Clear BSD license. See README for more details.
8 */
9
10#include "sigma_dut.h"
Vinita Maloo54b78cf2020-03-30 12:18:19 +053011#include <sys/ioctl.h>
Jouni Malinencd4e3c32015-10-29 12:39:56 +020012#include <sys/stat.h>
13#include "wpa_helpers.h"
14
15enum driver_type wifi_chip_type = DRIVER_NOT_SET;
16enum openwrt_driver_type openwrt_chip_type = OPENWRT_DRIVER_NOT_SET;
17
Vinita Maloo54b78cf2020-03-30 12:18:19 +053018struct wcn_drv_priv_cmd {
19 char *buf;
20 int used_len;
21 int total_len;
22};
Jouni Malinencd4e3c32015-10-29 12:39:56 +020023
24int file_exists(const char *fname)
25{
26 struct stat s;
27 return stat(fname, &s) == 0;
28}
29
30
31int 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;
Sreelakshmi Konamkib692f102016-04-26 19:47:00 +053045 else if (!strncmp(chip_type, "LINUX-WCN", strlen("LINUX-WCN")))
46 wifi_chip_type = DRIVER_LINUX_WCN;
Jouni Malinencd4e3c32015-10-29 12:39:56 +020047 else
48 return -1;
49
50 return 0;
51}
52
53
Jouni Malinen016ae6c2019-11-04 17:00:01 +020054enum driver_type get_driver_type(struct sigma_dut *dut)
Jouni Malinencd4e3c32015-10-29 12:39:56 +020055{
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];
Jouni Malinen016ae6c2019-11-04 17:00:01 +020062 const char *ifname = get_station_ifname(dut);
Jouni Malinencd4e3c32015-10-29 12:39:56 +020063
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
Venkateswara Naralasettyf0f88052020-11-11 19:15:17 +053081void 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
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200115enum openwrt_driver_type get_openwrt_driver_type(void)
116{
117 struct stat s;
118
119 if (openwrt_chip_type == OPENWRT_DRIVER_NOT_SET) {
priyadharshini gowthaman00bbdf12018-01-29 12:42:00 -0800120 if (stat("/sys/module/umac", &s) == 0 ||
121 stat("/sys/module/atd", &s) == 0)
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200122 openwrt_chip_type = OPENWRT_DRIVER_ATHEROS;
123 }
124
125 return openwrt_chip_type;
126}
127
128
129enum 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 ||
Jouni Malinenba630452018-06-22 11:49:59 +0300139 strcasecmp(prog, "HS2-R2") == 0)
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200140 return PROGRAM_HS2_R2;
Jouni Malinenba630452018-06-22 11:49:59 +0300141 if (strcasecmp(prog, "HS2-R3") == 0)
142 return PROGRAM_HS2_R3;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200143 if (strcasecmp(prog, "WFD") == 0)
144 return PROGRAM_WFD;
Amarnath Hullur Subramanyam659a34c2017-03-17 00:04:41 -0700145 if (strcasecmp(prog, "DisplayR2") == 0)
146 return PROGRAM_DISPLAYR2;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200147 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;
priyadharshini gowthaman12dd4142016-06-22 22:47:14 -0700159 if (strcasecmp(prog, "LOC") == 0)
160 return PROGRAM_LOC;
priyadharshini gowthamanb4e05fc2016-10-13 15:02:35 -0700161 if (strcasecmp(prog, "MBO") == 0)
162 return PROGRAM_MBO;
Adil Saeed Musthafa33ea2872017-04-10 23:13:24 -0700163 if (strcasecmp(prog, "IoTLP") == 0)
164 return PROGRAM_IOTLP;
Jouni Malinen5c3813a2017-08-26 13:30:39 +0300165 if (strcasecmp(prog, "DPP") == 0)
166 return PROGRAM_DPP;
Ankita Bajaja2cb5672017-10-25 16:08:28 +0530167 if (strcasecmp(prog, "OCE") == 0)
168 return PROGRAM_OCE;
priyadharshini gowthaman0e209fc2018-01-26 15:15:37 -0800169 if (strcasecmp(prog, "WPA3") == 0)
170 return PROGRAM_WPA3;
Amarnath Hullur Subramanyam8f9c8682018-01-30 19:01:51 -0800171 if (strcasecmp(prog, "HE") == 0)
172 return PROGRAM_HE;
Vamsi Krishnaf642d6a2020-03-27 12:33:14 +0530173 if (strcasecmp(prog, "QM") == 0)
174 return PROGRAM_QM;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200175
176 return PROGRAM_UNKNOWN;
177}
priyadharshini gowthaman72462ef2016-06-22 22:47:14 -0700178
179
180static 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
Alexei Avshalom Lazar9a4f98d2019-05-02 13:35:22 +0300192int hex_byte(const char *str)
priyadharshini gowthaman72462ef2016-06-22 22:47:14 -0700193{
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
Jouni Malinen08cf2312017-09-04 13:39:47 +0300206int 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
priyadharshini gowthaman72462ef2016-06-22 22:47:14 -0700227int 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
253fail:
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}
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700259
260
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200261int is_60g_sigma_dut(struct sigma_dut *dut)
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700262{
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200263 return dut->program == PROGRAM_60GHZ ||
264 (dut->program == PROGRAM_WPS &&
Jouni Malinen016ae6c2019-11-04 17:00:01 +0200265 (get_driver_type(dut) == DRIVER_WIL6210));
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200266}
267
268
269unsigned 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
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700278 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
289unsigned 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;
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200297 if (freq >= 58320 && freq <= 64800)
298 return (freq - 58320) / 2160;
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700299 return 0;
300}
Peng Xu769731a2017-05-10 17:27:28 -0700301
302
Peng Xu525965b2018-06-26 16:40:14 -0700303int 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
Rakesh Sunki8f8e74b2017-05-16 15:42:12 -0700311void 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
Peng Xu8863ec72018-08-06 11:50:37 -0700322size_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
Peng Xu769731a2017-05-10 17:27:28 -0700343#ifndef ANDROID
344
345size_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
370size_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 */
Ankita Bajaj1bde7942018-01-09 19:15:01 +0530391
392
393void 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}
Peng Xu291d97d2018-01-31 16:34:03 -0800412
413
414#ifdef NL80211_SUPPORT
415
416void * 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
424static struct nl_msg *
425nl80211_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
447struct 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
454static int ack_handler(struct nl_msg *msg, void *arg)
455{
456 int *err = arg;
457 *err = 0;
458 return NL_STOP;
459}
460
461
462static int finish_handler(struct nl_msg *msg, void *arg)
463{
464 int *ret = arg;
465 *ret = 0;
466 return NL_SKIP;
467}
468
469
470static 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
479int 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
537struct 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
586cleanup:
587 if (ctx->sock)
588 nl_socket_free(ctx->sock);
589
590 free(ctx);
591 return NULL;
592}
593
594
595void 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
Veerendranath Jakkam050b85a2020-07-04 04:00:32 +0530606
607static struct nl_msg *
608wcn_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
635static 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
654int 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
674int 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
694int 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
Peng Xu291d97d2018-01-31 16:34:03 -0800713#endif /* NL80211_SUPPORT */
Alexei Avshalom Lazar64279692018-12-23 16:49:49 +0200714
715
Alexei Avshalom Lazar0dae51c2018-12-18 16:00:18 +0200716static 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
731int 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
Alexei Avshalom Lazar744ae8a2019-01-31 17:26:46 +0200755int 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
Alexei Avshalom Lazar64279692018-12-23 16:49:49 +0200774void 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}
Alexei Avshalom Lazara37dc162019-02-04 14:06:48 +0200785
786
787static const char base64_table[65] =
788 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
789
790
791int 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
833int 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}
Jouni Malinen3c740ab2019-10-10 15:55:11 +0300847
848
849int 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}
Vinita Maloo54b78cf2020-03-30 12:18:19 +0530858
859
860int 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}
Veerendranath Jakkam176181c2020-05-16 00:19:21 +0530885
886
887int 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}