blob: c470937e912bd615db634862df7149a947fd5c93 [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.
Jouni Malinen2feb9132021-11-16 00:53:06 +02004 * Copyright (c) 2018-2021, 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 Malinen9a742ff2022-01-27 00:43:14 +0200143 if (strcasecmp(prog, "HS2-R4") == 0)
144 return PROGRAM_HS2_R4;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200145 if (strcasecmp(prog, "WFD") == 0)
146 return PROGRAM_WFD;
Amarnath Hullur Subramanyam659a34c2017-03-17 00:04:41 -0700147 if (strcasecmp(prog, "DisplayR2") == 0)
148 return PROGRAM_DISPLAYR2;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200149 if (strcasecmp(prog, "PMF") == 0)
150 return PROGRAM_PMF;
151 if (strcasecmp(prog, "WPS") == 0)
152 return PROGRAM_WPS;
153 if (strcasecmp(prog, "11n") == 0)
154 return PROGRAM_HT;
155 if (strcasecmp(prog, "VHT") == 0)
156 return PROGRAM_VHT;
157 if (strcasecmp(prog, "60GHZ") == 0)
158 return PROGRAM_60GHZ;
159 if (strcasecmp(prog, "NAN") == 0)
160 return PROGRAM_NAN;
priyadharshini gowthaman12dd4142016-06-22 22:47:14 -0700161 if (strcasecmp(prog, "LOC") == 0)
162 return PROGRAM_LOC;
priyadharshini gowthamanb4e05fc2016-10-13 15:02:35 -0700163 if (strcasecmp(prog, "MBO") == 0)
164 return PROGRAM_MBO;
Adil Saeed Musthafa33ea2872017-04-10 23:13:24 -0700165 if (strcasecmp(prog, "IoTLP") == 0)
166 return PROGRAM_IOTLP;
Jouni Malinen5c3813a2017-08-26 13:30:39 +0300167 if (strcasecmp(prog, "DPP") == 0)
168 return PROGRAM_DPP;
Ankita Bajaja2cb5672017-10-25 16:08:28 +0530169 if (strcasecmp(prog, "OCE") == 0)
170 return PROGRAM_OCE;
priyadharshini gowthaman0e209fc2018-01-26 15:15:37 -0800171 if (strcasecmp(prog, "WPA3") == 0)
172 return PROGRAM_WPA3;
Amarnath Hullur Subramanyam8f9c8682018-01-30 19:01:51 -0800173 if (strcasecmp(prog, "HE") == 0)
174 return PROGRAM_HE;
Vamsi Krishnaf642d6a2020-03-27 12:33:14 +0530175 if (strcasecmp(prog, "QM") == 0)
176 return PROGRAM_QM;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200177
178 return PROGRAM_UNKNOWN;
179}
priyadharshini gowthaman72462ef2016-06-22 22:47:14 -0700180
181
182static int parse_hex(char c)
183{
184 if (c >= '0' && c <= '9')
185 return c - '0';
186 if (c >= 'a' && c <= 'f')
187 return c - 'a' + 10;
188 if (c >= 'A' && c <= 'F')
189 return c - 'A' + 10;
190 return -1;
191}
192
193
Alexei Avshalom Lazar9a4f98d2019-05-02 13:35:22 +0300194int hex_byte(const char *str)
priyadharshini gowthaman72462ef2016-06-22 22:47:14 -0700195{
196 int res1, res2;
197
198 res1 = parse_hex(str[0]);
199 if (res1 < 0)
200 return -1;
201 res2 = parse_hex(str[1]);
202 if (res2 < 0)
203 return -1;
204 return (res1 << 4) | res2;
205}
206
207
Jouni Malinen08cf2312017-09-04 13:39:47 +0300208int parse_hexstr(const char *hex, unsigned char *buf, size_t buflen)
209{
210 size_t i;
211 const char *pos = hex;
212
213 for (i = 0; i < buflen; i++) {
214 int val;
215
216 if (*pos == '\0')
217 break;
218 val = hex_byte(pos);
219 if (val < 0)
220 return -1;
221 buf[i] = val;
222 pos += 2;
223 }
224
225 return i;
226}
227
228
priyadharshini gowthaman72462ef2016-06-22 22:47:14 -0700229int parse_mac_address(struct sigma_dut *dut, const char *arg,
230 unsigned char *addr)
231{
232 int i;
233 const char *pos = arg;
234
235 if (strlen(arg) != 17)
236 goto fail;
237
238 for (i = 0; i < ETH_ALEN; i++) {
239 int val;
240
241 val = hex_byte(pos);
242 if (val < 0)
243 goto fail;
244 addr[i] = val;
245 if (i + 1 < ETH_ALEN) {
246 pos += 2;
247 if (*pos != ':')
248 goto fail;
249 pos++;
250 }
251 }
252
253 return 0;
254
255fail:
256 sigma_dut_print(dut, DUT_MSG_ERROR,
257 "Invalid MAC address %s (expected format xx:xx:xx:xx:xx:xx)",
258 arg);
259 return -1;
260}
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700261
262
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200263int is_60g_sigma_dut(struct sigma_dut *dut)
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700264{
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200265 return dut->program == PROGRAM_60GHZ ||
266 (dut->program == PROGRAM_WPS &&
Jouni Malinen016ae6c2019-11-04 17:00:01 +0200267 (get_driver_type(dut) == DRIVER_WIL6210));
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200268}
269
270
271unsigned int channel_to_freq(struct sigma_dut *dut, unsigned int channel)
272{
273 if (is_60g_sigma_dut(dut)) {
274 if (channel >= 1 && channel <= 4)
275 return 58320 + 2160 * channel;
276
277 return 0;
278 }
279
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700280 if (channel >= 1 && channel <= 13)
281 return 2407 + 5 * channel;
282 if (channel == 14)
283 return 2484;
284 if (channel >= 36 && channel <= 165)
285 return 5000 + 5 * channel;
286
287 return 0;
288}
289
290
291unsigned int freq_to_channel(unsigned int freq)
292{
293 if (freq >= 2412 && freq <= 2472)
294 return (freq - 2407) / 5;
295 if (freq == 2484)
296 return 14;
297 if (freq >= 5180 && freq <= 5825)
298 return (freq - 5000) / 5;
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200299 if (freq >= 58320 && freq <= 64800)
300 return (freq - 58320) / 2160;
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700301 return 0;
302}
Peng Xu769731a2017-05-10 17:27:28 -0700303
304
Peng Xu525965b2018-06-26 16:40:14 -0700305int is_ipv6_addr(const char *str)
306{
307 struct sockaddr_in6 addr;
308
309 return inet_pton(AF_INET6, str, &(addr.sin6_addr));
310}
311
312
Rakesh Sunki8f8e74b2017-05-16 15:42:12 -0700313void convert_mac_addr_to_ipv6_lladdr(u8 *mac_addr, char *ipv6_buf,
314 size_t buf_len)
315{
316 u8 temp = mac_addr[0] ^ 0x02;
317
318 snprintf(ipv6_buf, buf_len, "fe80::%02x%02x:%02xff:fe%02x:%02x%02x",
319 temp, mac_addr[1], mac_addr[2],
320 mac_addr[3], mac_addr[4], mac_addr[5]);
321}
322
323
Peng Xu8863ec72018-08-06 11:50:37 -0700324size_t convert_mac_addr_to_ipv6_linklocal(const u8 *mac_addr, u8 *ipv6)
325{
326 int i;
327
328 ipv6[0] = 0xfe;
329 ipv6[1] = 0x80;
330 for (i = 2; i < 8; i++)
331 ipv6[i] = 0;
332 ipv6[8] = mac_addr[0] ^ 0x02;
333 ipv6[9] = mac_addr[1];
334 ipv6[10] = mac_addr[2];
335 ipv6[11] = 0xff;
336 ipv6[12] = 0xfe;
337 ipv6[13] = mac_addr[3];
338 ipv6[14] = mac_addr[4];
339 ipv6[15] = mac_addr[5];
340
341 return 16;
342}
343
344
Peng Xu769731a2017-05-10 17:27:28 -0700345#ifndef ANDROID
346
347size_t strlcpy(char *dest, const char *src, size_t siz)
348{
349 const char *s = src;
350 size_t left = siz;
351
352 if (left) {
353 /* Copy string up to the maximum size of the dest buffer */
354 while (--left != 0) {
355 if ((*dest++ = *s++) == '\0')
356 break;
357 }
358 }
359
360 if (left == 0) {
361 /* Not enough room for the string; force NUL-termination */
362 if (siz != 0)
363 *dest = '\0';
364 while (*s++)
365 ; /* determine total src string length */
366 }
367
368 return s - src - 1;
369}
370
371
372size_t strlcat(char *dst, const char *str, size_t size)
373{
374 char *pos;
375 size_t dstlen, srclen, copy;
376
377 srclen = strlen(str);
P Praneeshbce09062021-07-13 18:57:16 +0530378 dstlen = strlen(dst);
379 pos = dst + dstlen;
380
381 if (dstlen >= size)
Peng Xu769731a2017-05-10 17:27:28 -0700382 return dstlen + srclen;
P Praneeshbce09062021-07-13 18:57:16 +0530383
384 if (dstlen + srclen >= size)
Peng Xu769731a2017-05-10 17:27:28 -0700385 copy = size - dstlen - 1;
386 else
387 copy = srclen;
P Praneeshbce09062021-07-13 18:57:16 +0530388
Peng Xu769731a2017-05-10 17:27:28 -0700389 memcpy(pos, str, copy);
390 pos[copy] = '\0';
391 return dstlen + srclen;
392}
393
394#endif /* ANDROID */
Ankita Bajaj1bde7942018-01-09 19:15:01 +0530395
396
397void hex_dump(struct sigma_dut *dut, u8 *data, size_t len)
398{
399 char buf[1024];
400 size_t index;
401 u8 *ptr;
402 int pos;
403
404 memset(buf, 0, sizeof(buf));
405 ptr = data;
406 pos = 0;
407 for (index = 0; index < len; index++) {
408 pos += snprintf(&(buf[pos]), sizeof(buf) - pos,
409 "%02x ", *ptr++);
410 if (pos > 1020)
411 break;
412 }
413 sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len);
414 sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf);
415}
Peng Xu291d97d2018-01-31 16:34:03 -0800416
417
418#ifdef NL80211_SUPPORT
419
420void * nl80211_cmd(struct sigma_dut *dut, struct nl80211_ctx *ctx,
421 struct nl_msg *msg, int flags, uint8_t cmd)
422{
Sai Pavan Akhil Remella6469f0c2021-12-20 15:49:53 +0530423 if (!ctx)
424 return NULL;
Peng Xu291d97d2018-01-31 16:34:03 -0800425 return genlmsg_put(msg, 0, 0, ctx->netlink_familyid,
426 0, flags, cmd, 0);
427}
428
429
430static struct nl_msg *
431nl80211_ifindex_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx, int ifindex,
432 int flags, uint8_t cmd)
433{
434 struct nl_msg *msg;
435
436 msg = nlmsg_alloc();
437 if (!msg) {
438 sigma_dut_print(dut, DUT_MSG_ERROR,
439 "Failed to allocate NL message");
440 return NULL;
441 }
442
443 if (!nl80211_cmd(dut, ctx, msg, flags, cmd) ||
444 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
445 nlmsg_free(msg);
446 return NULL;
447 }
448
449 return msg;
450}
451
452
453struct nl_msg * nl80211_drv_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx,
454 int ifindex, int flags, uint8_t cmd)
455{
456 return nl80211_ifindex_msg(dut, ctx, ifindex, flags, cmd);
457}
458
459
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700460static int no_seq_check(struct nl_msg *msg, void *arg)
461{
462 return NL_OK;
463}
464
465
Peng Xu291d97d2018-01-31 16:34:03 -0800466static int ack_handler(struct nl_msg *msg, void *arg)
467{
468 int *err = arg;
469 *err = 0;
470 return NL_STOP;
471}
472
473
474static int finish_handler(struct nl_msg *msg, void *arg)
475{
476 int *ret = arg;
477 *ret = 0;
478 return NL_SKIP;
479}
480
481
482static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
483 void *arg)
484{
485 int *ret = arg;
486 *ret = err->error;
487 return NL_SKIP;
488}
489
490
491int send_and_recv_msgs(struct sigma_dut *dut, struct nl80211_ctx *ctx,
492 struct nl_msg *nlmsg,
493 int (*valid_handler)(struct nl_msg *, void *),
494 void *valid_data)
495{
496 struct nl_cb *cb;
497 int err = -ENOMEM;
498
499 if (!nlmsg)
500 return -ENOMEM;
501
502 cb = nl_cb_alloc(NL_CB_DEFAULT);
503 if (!cb)
504 goto out;
505
506 err = nl_send_auto_complete(ctx->sock, nlmsg);
507 if (err < 0) {
508 sigma_dut_print(dut, DUT_MSG_ERROR,
509 "nl80211: failed to send err=%d", err);
510 goto out;
511 }
512
513 err = 1;
514
515 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
516 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
517 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
518
519 if (valid_handler)
520 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
521 valid_handler, valid_data);
522
523 while (err > 0) {
524 int res = nl_recvmsgs(ctx->sock, cb);
525
526 if (res < 0) {
527 sigma_dut_print(dut, DUT_MSG_ERROR,
528 "nl80211: %s->nl_recvmsgs failed: res=%d, err=%d",
529 __func__, res, err);
530 }
531 }
532 out:
533 nl_cb_put(cb);
534 if (!valid_handler && valid_data == (void *) -1) {
535 if (nlmsg) {
536 struct nlmsghdr *hdr = nlmsg_hdr(nlmsg);
537 void *data = nlmsg_data(hdr);
538 int len = hdr->nlmsg_len - NLMSG_HDRLEN;
539
540 memset(data, 0, len);
541 }
542 }
543
544 nlmsg_free(nlmsg);
545 return err;
546}
547
548
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700549struct family_data {
550 struct sigma_dut *dut;
551 const char *group;
552 int id;
553};
554
555static int family_handler(struct nl_msg *msg, void *arg)
556{
557 struct family_data *res = arg;
558 struct nlattr *tb[CTRL_ATTR_MAX + 1];
559 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
560 struct nlattr *mcgrp;
561 int i;
562 struct sigma_dut *dut = res->dut;
563
564 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
565 genlmsg_attrlen(gnlh, 0), NULL);
566
567 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
568 sigma_dut_print(dut, DUT_MSG_ERROR,
569 "mcast groups is not present");
570 return NL_SKIP;
571 }
572
573 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
574 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
575
576 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
577 nla_len(mcgrp), NULL);
578 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
579 !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
580 strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
581 res->group,
582 nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
583 continue;
584 res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
585 break;
586 };
587
588 return NL_SKIP;
589}
590
591
592static int nl_get_multicast_id(struct sigma_dut *dut, struct nl80211_ctx *ctx,
593 const char *family, const char *group)
594{
595 struct nl_msg *msg;
596 int ret;
597 struct family_data res = { dut, group, -ENOENT };
598
599 res.dut = dut;
600
601 msg = nlmsg_alloc();
602 if (!msg)
603 return -ENOMEM;
604 if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(ctx->sock, "nlctrl"),
605 0, 0, CTRL_CMD_GETFAMILY, 0) ||
606 nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) {
607 nlmsg_free(msg);
608 return -1;
609 }
610
611 ret = send_and_recv_msgs(dut, ctx, msg, family_handler, &res);
612 if (ret == 0)
613 ret = res.id;
614 return ret;
615}
616
617
Peng Xu291d97d2018-01-31 16:34:03 -0800618struct nl80211_ctx * nl80211_init(struct sigma_dut *dut)
619{
620 struct nl80211_ctx *ctx;
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700621 struct nl_cb *cb = NULL;
622 int ret;
Peng Xu291d97d2018-01-31 16:34:03 -0800623
624 ctx = calloc(1, sizeof(struct nl80211_ctx));
625 if (!ctx) {
626 sigma_dut_print(dut, DUT_MSG_ERROR,
627 "Failed to alloc nl80211_ctx");
628 return NULL;
629 }
630
631 ctx->sock = nl_socket_alloc();
632 if (!ctx->sock) {
633 sigma_dut_print(dut, DUT_MSG_ERROR,
634 "Failed to create NL socket, err: %s",
635 strerror(errno));
636 goto cleanup;
637 }
638
639 if (nl_connect(ctx->sock, NETLINK_GENERIC)) {
640 sigma_dut_print(dut, DUT_MSG_ERROR,
641 "Could not connect socket, err: %s",
642 strerror(errno));
643 goto cleanup;
644 }
645
646 if (nl_socket_set_buffer_size(ctx->sock, SOCK_BUF_SIZE, 0) < 0) {
647 sigma_dut_print(dut, DUT_MSG_INFO,
648 "Could not set nl_socket RX buffer size for sock: %s",
649 strerror(errno));
650 }
651
652 ctx->netlink_familyid = genl_ctrl_resolve(ctx->sock, "nl80211");
653 if (ctx->netlink_familyid < 0) {
654 sigma_dut_print(dut, DUT_MSG_ERROR,
655 "Could not resolve nl80211 family id");
656 goto cleanup;
657 }
658
659 ctx->nlctrl_familyid = genl_ctrl_resolve(ctx->sock, "nlctrl");
660 if (ctx->nlctrl_familyid < 0) {
661 sigma_dut_print(dut, DUT_MSG_ERROR,
662 "net link family nlctrl is not present: %d err:%s",
663 ctx->nlctrl_familyid, strerror(errno));
664 goto cleanup;
665 }
666
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700667 ctx->event_sock = nl_socket_alloc();
668 if (!ctx->event_sock) {
669 sigma_dut_print(dut, DUT_MSG_ERROR,
670 "Failed to create NL event socket, err: %s",
671 strerror(errno));
672 goto cleanup;
673 }
674
675 if (nl_connect(ctx->event_sock, NETLINK_GENERIC)) {
676 sigma_dut_print(dut, DUT_MSG_ERROR,
677 "Could not connect event socket, err: %s",
678 strerror(errno));
679 goto cleanup;
680 }
681
682 if (nl_socket_set_buffer_size(ctx->event_sock, SOCK_BUF_SIZE, 0) < 0) {
683 sigma_dut_print(dut, DUT_MSG_INFO,
684 "Fail to set nl_socket RX buff size for event sock: %s",
685 strerror(errno));
686 }
687
688 cb = nl_socket_get_cb(ctx->event_sock);
689 if (!cb) {
690 sigma_dut_print(dut, DUT_MSG_INFO,
691 "Failed to get NL control block for event socket port");
692 goto cleanup;
693 }
694
695 ret = nl_get_multicast_id(dut, ctx, "nl80211", "vendor");
696 if (ret >= 0)
697 ret = nl_socket_add_membership(ctx->event_sock, ret);
698 if (ret < 0) {
699 sigma_dut_print(dut, DUT_MSG_INFO,
700 "nl80211: Could not add multicast "
701 "membership for vendor events: %d (%s)",
702 ret, nl_geterror(ret));
703 /* Continue without vendor events */
704 }
705 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
706 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &ret);
707 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &ret);
708 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
709 nl_cb_put(cb);
710
Peng Xu291d97d2018-01-31 16:34:03 -0800711 return ctx;
712
713cleanup:
714 if (ctx->sock)
715 nl_socket_free(ctx->sock);
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700716 if (ctx->event_sock)
717 nl_socket_free(ctx->event_sock);
Peng Xu291d97d2018-01-31 16:34:03 -0800718
719 free(ctx);
720 return NULL;
721}
722
723
724void nl80211_deinit(struct sigma_dut *dut, struct nl80211_ctx *ctx)
725{
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700726 if (!ctx) {
727 sigma_dut_print(dut, DUT_MSG_ERROR, "%s: ctx is NULL",
Peng Xu291d97d2018-01-31 16:34:03 -0800728 __func__);
729 return;
730 }
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700731 if (ctx->sock)
732 nl_socket_free(ctx->sock);
733 if (ctx->event_sock)
734 nl_socket_free(ctx->event_sock);
Peng Xu291d97d2018-01-31 16:34:03 -0800735 free(ctx);
736}
737
Veerendranath Jakkam050b85a2020-07-04 04:00:32 +0530738
739static struct nl_msg *
740wcn_create_wifi_test_config_msg(struct sigma_dut *dut, const char *intf)
741{
742 int ifindex;
743 struct nl_msg *msg;
744
745 ifindex = if_nametoindex(intf);
746 if (ifindex == 0) {
747 sigma_dut_print(dut, DUT_MSG_ERROR,
748 "%s: Index for interface %s failed",
749 __func__, intf);
750 return NULL;
751 }
752
753 if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
754 NL80211_CMD_VENDOR)) ||
755 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
756 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
757 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
758 QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION)) {
759 nlmsg_free(msg);
760 return NULL;
761 }
762
763 return msg;
764}
765
766
767static int wcn_send_wifi_test_config_msg(struct sigma_dut *dut,
768 struct nl_msg *msg,
769 struct nlattr *params, int attr_id)
770{
771 int ret;
772
773 nla_nest_end(msg, params);
774
775 ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
776 if (ret) {
777 sigma_dut_print(dut, DUT_MSG_ERROR,
778 "%s: err in send_and_recv_msgs, ret=%d for %d",
779 __func__, ret, attr_id);
780 }
781
782 return ret;
783}
784
785
786int wcn_wifi_test_config_set_flag(struct sigma_dut *dut, const char *intf,
787 int attr_id)
788{
789 struct nl_msg *msg;
790 struct nlattr *params;
791
792 if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
793 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
794 nla_put_flag(msg, attr_id)) {
795 sigma_dut_print(dut, DUT_MSG_ERROR,
796 "%s: err in adding test config data for %d",
797 __func__, attr_id);
798 nlmsg_free(msg);
799 return -1;
800 }
801
802 return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
803}
804
805
806int wcn_wifi_test_config_set_u8(struct sigma_dut *dut, const char *intf,
807 int attr_id, uint8_t val)
808{
809 struct nl_msg *msg;
810 struct nlattr *params;
811
812 if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
813 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
814 nla_put_u8(msg, attr_id, val)) {
815 sigma_dut_print(dut, DUT_MSG_ERROR,
816 "%s: err in adding test config data for %d",
817 __func__, attr_id);
818 nlmsg_free(msg);
819 return -1;
820 }
821
822 return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
823}
824
825
826int wcn_wifi_test_config_set_u16(struct sigma_dut *dut, const char *intf,
827 int attr_id, uint16_t val)
828{
829 struct nl_msg *msg;
830 struct nlattr *params;
831
832 if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
833 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
834 nla_put_u16(msg, attr_id, val)) {
835 sigma_dut_print(dut, DUT_MSG_ERROR,
836 "%s: err in adding test config data for %d",
837 __func__, attr_id);
838 nlmsg_free(msg);
839 return -1;
840 }
841
842 return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
843}
844
Peng Xu291d97d2018-01-31 16:34:03 -0800845#endif /* NL80211_SUPPORT */
Alexei Avshalom Lazar64279692018-12-23 16:49:49 +0200846
847
Alexei Avshalom Lazar0dae51c2018-12-18 16:00:18 +0200848static int get_wps_pin_checksum(int pin)
849{
850 int a = 0;
851
852 while (pin > 0) {
853 a += 3 * (pin % 10);
854 pin = pin / 10;
855 a += (pin % 10);
856 pin = pin / 10;
857 }
858
859 return (10 - (a % 10)) % 10;
860}
861
862
863int get_wps_pin_from_mac(struct sigma_dut *dut, const char *macaddr,
864 char *pin, size_t len)
865{
866 unsigned char mac[ETH_ALEN];
867 int tmp, checksum;
868
869 if (len < 9)
870 return -1;
871 if (parse_mac_address(dut, macaddr, mac))
872 return -1;
873
874 /*
875 * get 7 digit PIN from the last 24 bits of MAC
876 * range 1000000 - 9999999
877 */
878 tmp = (mac[5] & 0xFF) | ((mac[4] & 0xFF) << 8) |
879 ((mac[3] & 0xFF) << 16);
880 tmp = (tmp % 9000000) + 1000000;
881 checksum = get_wps_pin_checksum(tmp);
882 snprintf(pin, len, "%07d%01d", tmp, checksum);
883 return 0;
884}
885
886
Alexei Avshalom Lazar744ae8a2019-01-31 17:26:46 +0200887int get_wps_forced_version(struct sigma_dut *dut, const char *str)
888{
889 int major, minor, result = 0;
890 int count = sscanf(str, "%d.%d", &major, &minor);
891
892 if (count == 2) {
893 result = major * 16 + minor;
894 sigma_dut_print(dut, DUT_MSG_DEBUG,
895 "Force WPS version to 0x%02x (%s)",
896 result, str);
897 } else {
898 sigma_dut_print(dut, DUT_MSG_ERROR,
899 "Invalid WPS version %s", str);
900 }
901
902 return result;
903}
904
905
Alexei Avshalom Lazar64279692018-12-23 16:49:49 +0200906void str_remove_chars(char *str, char ch)
907{
908 char *pr = str, *pw = str;
909
910 while (*pr) {
911 *pw = *pr++;
912 if (*pw != ch)
913 pw++;
914 }
915 *pw = '\0';
916}
Alexei Avshalom Lazara37dc162019-02-04 14:06:48 +0200917
918
919static const char base64_table[65] =
920 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
921
922
923int base64_encode(const char *src, size_t len, char *out, size_t out_len)
924{
925 unsigned char *pos;
926 const unsigned char *end, *in;
927 size_t olen;
928
929 olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
930 olen++; /* nul termination */
931 if (olen < len || olen > out_len)
932 return -1;
933
934 end = (unsigned char *)(src + len);
935 in = (unsigned char *)src;
936 pos = (unsigned char *)out;
937 while (end - in >= 3) {
938 *pos++ = base64_table[(in[0] >> 2) & 0x3f];
939 *pos++ = base64_table[(((in[0] & 0x03) << 4) |
940 (in[1] >> 4)) & 0x3f];
941 *pos++ = base64_table[(((in[1] & 0x0f) << 2) |
942 (in[2] >> 6)) & 0x3f];
943 *pos++ = base64_table[in[2] & 0x3f];
944 in += 3;
945 }
946
947 if (end - in) {
948 *pos++ = base64_table[(in[0] >> 2) & 0x3f];
949 if (end - in == 1) {
950 *pos++ = base64_table[((in[0] & 0x03) << 4) & 0x3f];
951 *pos++ = '=';
952 } else {
953 *pos++ = base64_table[(((in[0] & 0x03) << 4) |
954 (in[1] >> 4)) & 0x3f];
955 *pos++ = base64_table[((in[1] & 0x0f) << 2) & 0x3f];
956 }
957 *pos++ = '=';
958 }
959
960 *pos = '\0';
961 return 0;
962}
963
964
965int random_get_bytes(char *buf, size_t len)
966{
967 FILE *f;
968 size_t rc;
969
970 f = fopen("/dev/urandom", "rb");
971 if (!f)
972 return -1;
973
974 rc = fread(buf, 1, len, f);
975 fclose(f);
976
977 return rc != len ? -1 : 0;
978}
Jouni Malinen3c740ab2019-10-10 15:55:11 +0300979
980
981int get_enable_disable(const char *val)
982{
983 if (strcasecmp(val, "enable") == 0 ||
984 strcasecmp(val, "enabled") == 0 ||
985 strcasecmp(val, "on") == 0 ||
986 strcasecmp(val, "yes") == 0)
987 return 1;
988 return atoi(val);
989}
Vinita Maloo54b78cf2020-03-30 12:18:19 +0530990
991
992int wcn_driver_cmd(const char *ifname, char *buf)
993{
994 int s, res;
995 size_t buf_len;
996 struct wcn_drv_priv_cmd priv_cmd;
997 struct ifreq ifr;
998
999 s = socket(PF_INET, SOCK_DGRAM, 0);
1000 if (s < 0) {
1001 perror("socket");
1002 return -1;
1003 }
1004
1005 memset(&ifr, 0, sizeof(ifr));
1006 memset(&priv_cmd, 0, sizeof(priv_cmd));
1007 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1008 buf_len = strlen(buf);
1009 priv_cmd.buf = buf;
1010 priv_cmd.used_len = buf_len;
1011 priv_cmd.total_len = buf_len;
1012 ifr.ifr_data = (void *) &priv_cmd;
1013 res = ioctl(s, SIOCDEVPRIVATE + 1, &ifr);
1014 close(s);
1015 return res;
1016}
Veerendranath Jakkam176181c2020-05-16 00:19:21 +05301017
1018
1019int set_ipv6_addr(struct sigma_dut *dut, const char *ip, const char *mask,
1020 const char *ifname)
1021{
1022 char buf[200];
1023
1024 snprintf(buf, sizeof(buf), "ip -6 addr del %s/%s dev %s", ip, mask,
1025 ifname);
1026 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
1027 if (system(buf) != 0) {
1028 /*
1029 * This command may fail if the address being deleted does not
1030 * exist. Inaction here is intentional.
1031 */
1032 }
1033
1034 snprintf(buf, sizeof(buf), "ip -6 addr add %s/%s dev %s", ip, mask,
1035 ifname);
1036 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
1037 if (system(buf) != 0)
1038 return -1;
1039
1040 return 0;
1041}
Veerendranath Jakkam9ceb3b12021-09-10 03:18:17 +05301042
1043
1044int snprintf_error(size_t size, int res)
1045{
1046 return res < 0 || (unsigned int) res >= size;
1047}