blob: cb69a99d9713e9b927157243347a39c803b55567 [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 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);
P Praneeshbce09062021-07-13 18:57:16 +0530376 dstlen = strlen(dst);
377 pos = dst + dstlen;
378
379 if (dstlen >= size)
Peng Xu769731a2017-05-10 17:27:28 -0700380 return dstlen + srclen;
P Praneeshbce09062021-07-13 18:57:16 +0530381
382 if (dstlen + srclen >= size)
Peng Xu769731a2017-05-10 17:27:28 -0700383 copy = size - dstlen - 1;
384 else
385 copy = srclen;
P Praneeshbce09062021-07-13 18:57:16 +0530386
Peng Xu769731a2017-05-10 17:27:28 -0700387 memcpy(pos, str, copy);
388 pos[copy] = '\0';
389 return dstlen + srclen;
390}
391
392#endif /* ANDROID */
Ankita Bajaj1bde7942018-01-09 19:15:01 +0530393
394
395void hex_dump(struct sigma_dut *dut, u8 *data, size_t len)
396{
397 char buf[1024];
398 size_t index;
399 u8 *ptr;
400 int pos;
401
402 memset(buf, 0, sizeof(buf));
403 ptr = data;
404 pos = 0;
405 for (index = 0; index < len; index++) {
406 pos += snprintf(&(buf[pos]), sizeof(buf) - pos,
407 "%02x ", *ptr++);
408 if (pos > 1020)
409 break;
410 }
411 sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len);
412 sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf);
413}
Peng Xu291d97d2018-01-31 16:34:03 -0800414
415
416#ifdef NL80211_SUPPORT
417
418void * nl80211_cmd(struct sigma_dut *dut, struct nl80211_ctx *ctx,
419 struct nl_msg *msg, int flags, uint8_t cmd)
420{
Sai Pavan Akhil Remella6469f0c2021-12-20 15:49:53 +0530421 if (!ctx)
422 return NULL;
Peng Xu291d97d2018-01-31 16:34:03 -0800423 return genlmsg_put(msg, 0, 0, ctx->netlink_familyid,
424 0, flags, cmd, 0);
425}
426
427
428static struct nl_msg *
429nl80211_ifindex_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx, int ifindex,
430 int flags, uint8_t cmd)
431{
432 struct nl_msg *msg;
433
434 msg = nlmsg_alloc();
435 if (!msg) {
436 sigma_dut_print(dut, DUT_MSG_ERROR,
437 "Failed to allocate NL message");
438 return NULL;
439 }
440
441 if (!nl80211_cmd(dut, ctx, msg, flags, cmd) ||
442 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
443 nlmsg_free(msg);
444 return NULL;
445 }
446
447 return msg;
448}
449
450
451struct nl_msg * nl80211_drv_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx,
452 int ifindex, int flags, uint8_t cmd)
453{
454 return nl80211_ifindex_msg(dut, ctx, ifindex, flags, cmd);
455}
456
457
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700458static int no_seq_check(struct nl_msg *msg, void *arg)
459{
460 return NL_OK;
461}
462
463
Peng Xu291d97d2018-01-31 16:34:03 -0800464static int ack_handler(struct nl_msg *msg, void *arg)
465{
466 int *err = arg;
467 *err = 0;
468 return NL_STOP;
469}
470
471
472static int finish_handler(struct nl_msg *msg, void *arg)
473{
474 int *ret = arg;
475 *ret = 0;
476 return NL_SKIP;
477}
478
479
480static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
481 void *arg)
482{
483 int *ret = arg;
484 *ret = err->error;
485 return NL_SKIP;
486}
487
488
489int send_and_recv_msgs(struct sigma_dut *dut, struct nl80211_ctx *ctx,
490 struct nl_msg *nlmsg,
491 int (*valid_handler)(struct nl_msg *, void *),
492 void *valid_data)
493{
494 struct nl_cb *cb;
495 int err = -ENOMEM;
496
497 if (!nlmsg)
498 return -ENOMEM;
499
500 cb = nl_cb_alloc(NL_CB_DEFAULT);
501 if (!cb)
502 goto out;
503
504 err = nl_send_auto_complete(ctx->sock, nlmsg);
505 if (err < 0) {
506 sigma_dut_print(dut, DUT_MSG_ERROR,
507 "nl80211: failed to send err=%d", err);
508 goto out;
509 }
510
511 err = 1;
512
513 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
514 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
515 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
516
517 if (valid_handler)
518 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
519 valid_handler, valid_data);
520
521 while (err > 0) {
522 int res = nl_recvmsgs(ctx->sock, cb);
523
524 if (res < 0) {
525 sigma_dut_print(dut, DUT_MSG_ERROR,
526 "nl80211: %s->nl_recvmsgs failed: res=%d, err=%d",
527 __func__, res, err);
528 }
529 }
530 out:
531 nl_cb_put(cb);
532 if (!valid_handler && valid_data == (void *) -1) {
533 if (nlmsg) {
534 struct nlmsghdr *hdr = nlmsg_hdr(nlmsg);
535 void *data = nlmsg_data(hdr);
536 int len = hdr->nlmsg_len - NLMSG_HDRLEN;
537
538 memset(data, 0, len);
539 }
540 }
541
542 nlmsg_free(nlmsg);
543 return err;
544}
545
546
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700547struct family_data {
548 struct sigma_dut *dut;
549 const char *group;
550 int id;
551};
552
553static int family_handler(struct nl_msg *msg, void *arg)
554{
555 struct family_data *res = arg;
556 struct nlattr *tb[CTRL_ATTR_MAX + 1];
557 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
558 struct nlattr *mcgrp;
559 int i;
560 struct sigma_dut *dut = res->dut;
561
562 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
563 genlmsg_attrlen(gnlh, 0), NULL);
564
565 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
566 sigma_dut_print(dut, DUT_MSG_ERROR,
567 "mcast groups is not present");
568 return NL_SKIP;
569 }
570
571 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
572 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
573
574 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
575 nla_len(mcgrp), NULL);
576 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
577 !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
578 strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
579 res->group,
580 nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
581 continue;
582 res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
583 break;
584 };
585
586 return NL_SKIP;
587}
588
589
590static int nl_get_multicast_id(struct sigma_dut *dut, struct nl80211_ctx *ctx,
591 const char *family, const char *group)
592{
593 struct nl_msg *msg;
594 int ret;
595 struct family_data res = { dut, group, -ENOENT };
596
597 res.dut = dut;
598
599 msg = nlmsg_alloc();
600 if (!msg)
601 return -ENOMEM;
602 if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(ctx->sock, "nlctrl"),
603 0, 0, CTRL_CMD_GETFAMILY, 0) ||
604 nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) {
605 nlmsg_free(msg);
606 return -1;
607 }
608
609 ret = send_and_recv_msgs(dut, ctx, msg, family_handler, &res);
610 if (ret == 0)
611 ret = res.id;
612 return ret;
613}
614
615
Peng Xu291d97d2018-01-31 16:34:03 -0800616struct nl80211_ctx * nl80211_init(struct sigma_dut *dut)
617{
618 struct nl80211_ctx *ctx;
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700619 struct nl_cb *cb = NULL;
620 int ret;
Peng Xu291d97d2018-01-31 16:34:03 -0800621
622 ctx = calloc(1, sizeof(struct nl80211_ctx));
623 if (!ctx) {
624 sigma_dut_print(dut, DUT_MSG_ERROR,
625 "Failed to alloc nl80211_ctx");
626 return NULL;
627 }
628
629 ctx->sock = nl_socket_alloc();
630 if (!ctx->sock) {
631 sigma_dut_print(dut, DUT_MSG_ERROR,
632 "Failed to create NL socket, err: %s",
633 strerror(errno));
634 goto cleanup;
635 }
636
637 if (nl_connect(ctx->sock, NETLINK_GENERIC)) {
638 sigma_dut_print(dut, DUT_MSG_ERROR,
639 "Could not connect socket, err: %s",
640 strerror(errno));
641 goto cleanup;
642 }
643
644 if (nl_socket_set_buffer_size(ctx->sock, SOCK_BUF_SIZE, 0) < 0) {
645 sigma_dut_print(dut, DUT_MSG_INFO,
646 "Could not set nl_socket RX buffer size for sock: %s",
647 strerror(errno));
648 }
649
650 ctx->netlink_familyid = genl_ctrl_resolve(ctx->sock, "nl80211");
651 if (ctx->netlink_familyid < 0) {
652 sigma_dut_print(dut, DUT_MSG_ERROR,
653 "Could not resolve nl80211 family id");
654 goto cleanup;
655 }
656
657 ctx->nlctrl_familyid = genl_ctrl_resolve(ctx->sock, "nlctrl");
658 if (ctx->nlctrl_familyid < 0) {
659 sigma_dut_print(dut, DUT_MSG_ERROR,
660 "net link family nlctrl is not present: %d err:%s",
661 ctx->nlctrl_familyid, strerror(errno));
662 goto cleanup;
663 }
664
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700665 ctx->event_sock = nl_socket_alloc();
666 if (!ctx->event_sock) {
667 sigma_dut_print(dut, DUT_MSG_ERROR,
668 "Failed to create NL event socket, err: %s",
669 strerror(errno));
670 goto cleanup;
671 }
672
673 if (nl_connect(ctx->event_sock, NETLINK_GENERIC)) {
674 sigma_dut_print(dut, DUT_MSG_ERROR,
675 "Could not connect event socket, err: %s",
676 strerror(errno));
677 goto cleanup;
678 }
679
680 if (nl_socket_set_buffer_size(ctx->event_sock, SOCK_BUF_SIZE, 0) < 0) {
681 sigma_dut_print(dut, DUT_MSG_INFO,
682 "Fail to set nl_socket RX buff size for event sock: %s",
683 strerror(errno));
684 }
685
686 cb = nl_socket_get_cb(ctx->event_sock);
687 if (!cb) {
688 sigma_dut_print(dut, DUT_MSG_INFO,
689 "Failed to get NL control block for event socket port");
690 goto cleanup;
691 }
692
693 ret = nl_get_multicast_id(dut, ctx, "nl80211", "vendor");
694 if (ret >= 0)
695 ret = nl_socket_add_membership(ctx->event_sock, ret);
696 if (ret < 0) {
697 sigma_dut_print(dut, DUT_MSG_INFO,
698 "nl80211: Could not add multicast "
699 "membership for vendor events: %d (%s)",
700 ret, nl_geterror(ret));
701 /* Continue without vendor events */
702 }
703 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
704 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &ret);
705 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &ret);
706 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
707 nl_cb_put(cb);
708
Peng Xu291d97d2018-01-31 16:34:03 -0800709 return ctx;
710
711cleanup:
712 if (ctx->sock)
713 nl_socket_free(ctx->sock);
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700714 if (ctx->event_sock)
715 nl_socket_free(ctx->event_sock);
Peng Xu291d97d2018-01-31 16:34:03 -0800716
717 free(ctx);
718 return NULL;
719}
720
721
722void nl80211_deinit(struct sigma_dut *dut, struct nl80211_ctx *ctx)
723{
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700724 if (!ctx) {
725 sigma_dut_print(dut, DUT_MSG_ERROR, "%s: ctx is NULL",
Peng Xu291d97d2018-01-31 16:34:03 -0800726 __func__);
727 return;
728 }
Kiran Kumar Lokeref61a7432021-06-24 00:19:19 -0700729 if (ctx->sock)
730 nl_socket_free(ctx->sock);
731 if (ctx->event_sock)
732 nl_socket_free(ctx->event_sock);
Peng Xu291d97d2018-01-31 16:34:03 -0800733 free(ctx);
734}
735
Veerendranath Jakkam050b85a2020-07-04 04:00:32 +0530736
737static struct nl_msg *
738wcn_create_wifi_test_config_msg(struct sigma_dut *dut, const char *intf)
739{
740 int ifindex;
741 struct nl_msg *msg;
742
743 ifindex = if_nametoindex(intf);
744 if (ifindex == 0) {
745 sigma_dut_print(dut, DUT_MSG_ERROR,
746 "%s: Index for interface %s failed",
747 __func__, intf);
748 return NULL;
749 }
750
751 if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
752 NL80211_CMD_VENDOR)) ||
753 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
754 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
755 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
756 QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION)) {
757 nlmsg_free(msg);
758 return NULL;
759 }
760
761 return msg;
762}
763
764
765static int wcn_send_wifi_test_config_msg(struct sigma_dut *dut,
766 struct nl_msg *msg,
767 struct nlattr *params, int attr_id)
768{
769 int ret;
770
771 nla_nest_end(msg, params);
772
773 ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
774 if (ret) {
775 sigma_dut_print(dut, DUT_MSG_ERROR,
776 "%s: err in send_and_recv_msgs, ret=%d for %d",
777 __func__, ret, attr_id);
778 }
779
780 return ret;
781}
782
783
784int wcn_wifi_test_config_set_flag(struct sigma_dut *dut, const char *intf,
785 int attr_id)
786{
787 struct nl_msg *msg;
788 struct nlattr *params;
789
790 if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
791 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
792 nla_put_flag(msg, attr_id)) {
793 sigma_dut_print(dut, DUT_MSG_ERROR,
794 "%s: err in adding test config data for %d",
795 __func__, attr_id);
796 nlmsg_free(msg);
797 return -1;
798 }
799
800 return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
801}
802
803
804int wcn_wifi_test_config_set_u8(struct sigma_dut *dut, const char *intf,
805 int attr_id, uint8_t val)
806{
807 struct nl_msg *msg;
808 struct nlattr *params;
809
810 if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
811 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
812 nla_put_u8(msg, attr_id, val)) {
813 sigma_dut_print(dut, DUT_MSG_ERROR,
814 "%s: err in adding test config data for %d",
815 __func__, attr_id);
816 nlmsg_free(msg);
817 return -1;
818 }
819
820 return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
821}
822
823
824int wcn_wifi_test_config_set_u16(struct sigma_dut *dut, const char *intf,
825 int attr_id, uint16_t val)
826{
827 struct nl_msg *msg;
828 struct nlattr *params;
829
830 if (!(msg = wcn_create_wifi_test_config_msg(dut, intf)) ||
831 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
832 nla_put_u16(msg, attr_id, val)) {
833 sigma_dut_print(dut, DUT_MSG_ERROR,
834 "%s: err in adding test config data for %d",
835 __func__, attr_id);
836 nlmsg_free(msg);
837 return -1;
838 }
839
840 return wcn_send_wifi_test_config_msg(dut, msg, params, attr_id);
841}
842
Peng Xu291d97d2018-01-31 16:34:03 -0800843#endif /* NL80211_SUPPORT */
Alexei Avshalom Lazar64279692018-12-23 16:49:49 +0200844
845
Alexei Avshalom Lazar0dae51c2018-12-18 16:00:18 +0200846static int get_wps_pin_checksum(int pin)
847{
848 int a = 0;
849
850 while (pin > 0) {
851 a += 3 * (pin % 10);
852 pin = pin / 10;
853 a += (pin % 10);
854 pin = pin / 10;
855 }
856
857 return (10 - (a % 10)) % 10;
858}
859
860
861int get_wps_pin_from_mac(struct sigma_dut *dut, const char *macaddr,
862 char *pin, size_t len)
863{
864 unsigned char mac[ETH_ALEN];
865 int tmp, checksum;
866
867 if (len < 9)
868 return -1;
869 if (parse_mac_address(dut, macaddr, mac))
870 return -1;
871
872 /*
873 * get 7 digit PIN from the last 24 bits of MAC
874 * range 1000000 - 9999999
875 */
876 tmp = (mac[5] & 0xFF) | ((mac[4] & 0xFF) << 8) |
877 ((mac[3] & 0xFF) << 16);
878 tmp = (tmp % 9000000) + 1000000;
879 checksum = get_wps_pin_checksum(tmp);
880 snprintf(pin, len, "%07d%01d", tmp, checksum);
881 return 0;
882}
883
884
Alexei Avshalom Lazar744ae8a2019-01-31 17:26:46 +0200885int get_wps_forced_version(struct sigma_dut *dut, const char *str)
886{
887 int major, minor, result = 0;
888 int count = sscanf(str, "%d.%d", &major, &minor);
889
890 if (count == 2) {
891 result = major * 16 + minor;
892 sigma_dut_print(dut, DUT_MSG_DEBUG,
893 "Force WPS version to 0x%02x (%s)",
894 result, str);
895 } else {
896 sigma_dut_print(dut, DUT_MSG_ERROR,
897 "Invalid WPS version %s", str);
898 }
899
900 return result;
901}
902
903
Alexei Avshalom Lazar64279692018-12-23 16:49:49 +0200904void str_remove_chars(char *str, char ch)
905{
906 char *pr = str, *pw = str;
907
908 while (*pr) {
909 *pw = *pr++;
910 if (*pw != ch)
911 pw++;
912 }
913 *pw = '\0';
914}
Alexei Avshalom Lazara37dc162019-02-04 14:06:48 +0200915
916
917static const char base64_table[65] =
918 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
919
920
921int base64_encode(const char *src, size_t len, char *out, size_t out_len)
922{
923 unsigned char *pos;
924 const unsigned char *end, *in;
925 size_t olen;
926
927 olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
928 olen++; /* nul termination */
929 if (olen < len || olen > out_len)
930 return -1;
931
932 end = (unsigned char *)(src + len);
933 in = (unsigned char *)src;
934 pos = (unsigned char *)out;
935 while (end - in >= 3) {
936 *pos++ = base64_table[(in[0] >> 2) & 0x3f];
937 *pos++ = base64_table[(((in[0] & 0x03) << 4) |
938 (in[1] >> 4)) & 0x3f];
939 *pos++ = base64_table[(((in[1] & 0x0f) << 2) |
940 (in[2] >> 6)) & 0x3f];
941 *pos++ = base64_table[in[2] & 0x3f];
942 in += 3;
943 }
944
945 if (end - in) {
946 *pos++ = base64_table[(in[0] >> 2) & 0x3f];
947 if (end - in == 1) {
948 *pos++ = base64_table[((in[0] & 0x03) << 4) & 0x3f];
949 *pos++ = '=';
950 } else {
951 *pos++ = base64_table[(((in[0] & 0x03) << 4) |
952 (in[1] >> 4)) & 0x3f];
953 *pos++ = base64_table[((in[1] & 0x0f) << 2) & 0x3f];
954 }
955 *pos++ = '=';
956 }
957
958 *pos = '\0';
959 return 0;
960}
961
962
963int random_get_bytes(char *buf, size_t len)
964{
965 FILE *f;
966 size_t rc;
967
968 f = fopen("/dev/urandom", "rb");
969 if (!f)
970 return -1;
971
972 rc = fread(buf, 1, len, f);
973 fclose(f);
974
975 return rc != len ? -1 : 0;
976}
Jouni Malinen3c740ab2019-10-10 15:55:11 +0300977
978
979int get_enable_disable(const char *val)
980{
981 if (strcasecmp(val, "enable") == 0 ||
982 strcasecmp(val, "enabled") == 0 ||
983 strcasecmp(val, "on") == 0 ||
984 strcasecmp(val, "yes") == 0)
985 return 1;
986 return atoi(val);
987}
Vinita Maloo54b78cf2020-03-30 12:18:19 +0530988
989
990int wcn_driver_cmd(const char *ifname, char *buf)
991{
992 int s, res;
993 size_t buf_len;
994 struct wcn_drv_priv_cmd priv_cmd;
995 struct ifreq ifr;
996
997 s = socket(PF_INET, SOCK_DGRAM, 0);
998 if (s < 0) {
999 perror("socket");
1000 return -1;
1001 }
1002
1003 memset(&ifr, 0, sizeof(ifr));
1004 memset(&priv_cmd, 0, sizeof(priv_cmd));
1005 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1006 buf_len = strlen(buf);
1007 priv_cmd.buf = buf;
1008 priv_cmd.used_len = buf_len;
1009 priv_cmd.total_len = buf_len;
1010 ifr.ifr_data = (void *) &priv_cmd;
1011 res = ioctl(s, SIOCDEVPRIVATE + 1, &ifr);
1012 close(s);
1013 return res;
1014}
Veerendranath Jakkam176181c2020-05-16 00:19:21 +05301015
1016
1017int set_ipv6_addr(struct sigma_dut *dut, const char *ip, const char *mask,
1018 const char *ifname)
1019{
1020 char buf[200];
1021
1022 snprintf(buf, sizeof(buf), "ip -6 addr del %s/%s dev %s", ip, mask,
1023 ifname);
1024 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
1025 if (system(buf) != 0) {
1026 /*
1027 * This command may fail if the address being deleted does not
1028 * exist. Inaction here is intentional.
1029 */
1030 }
1031
1032 snprintf(buf, sizeof(buf), "ip -6 addr add %s/%s dev %s", ip, mask,
1033 ifname);
1034 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
1035 if (system(buf) != 0)
1036 return -1;
1037
1038 return 0;
1039}
Veerendranath Jakkam9ceb3b12021-09-10 03:18:17 +05301040
1041
1042int snprintf_error(size_t size, int res)
1043{
1044 return res < 0 || (unsigned int) res >= size;
1045}