blob: 8c3dc2f03eee539af3d53f523690c050668620bd [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
81enum openwrt_driver_type get_openwrt_driver_type(void)
82{
83 struct stat s;
84
85 if (openwrt_chip_type == OPENWRT_DRIVER_NOT_SET) {
priyadharshini gowthaman00bbdf12018-01-29 12:42:00 -080086 if (stat("/sys/module/umac", &s) == 0 ||
87 stat("/sys/module/atd", &s) == 0)
Jouni Malinencd4e3c32015-10-29 12:39:56 +020088 openwrt_chip_type = OPENWRT_DRIVER_ATHEROS;
89 }
90
91 return openwrt_chip_type;
92}
93
94
95enum sigma_program sigma_program_to_enum(const char *prog)
96{
97 if (prog == NULL)
98 return PROGRAM_UNKNOWN;
99
100 if (strcasecmp(prog, "TDLS") == 0)
101 return PROGRAM_TDLS;
102 if (strcasecmp(prog, "HS2") == 0)
103 return PROGRAM_HS2;
104 if (strcasecmp(prog, "HS2_R2") == 0 ||
Jouni Malinenba630452018-06-22 11:49:59 +0300105 strcasecmp(prog, "HS2-R2") == 0)
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200106 return PROGRAM_HS2_R2;
Jouni Malinenba630452018-06-22 11:49:59 +0300107 if (strcasecmp(prog, "HS2-R3") == 0)
108 return PROGRAM_HS2_R3;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200109 if (strcasecmp(prog, "WFD") == 0)
110 return PROGRAM_WFD;
Amarnath Hullur Subramanyam659a34c2017-03-17 00:04:41 -0700111 if (strcasecmp(prog, "DisplayR2") == 0)
112 return PROGRAM_DISPLAYR2;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200113 if (strcasecmp(prog, "PMF") == 0)
114 return PROGRAM_PMF;
115 if (strcasecmp(prog, "WPS") == 0)
116 return PROGRAM_WPS;
117 if (strcasecmp(prog, "11n") == 0)
118 return PROGRAM_HT;
119 if (strcasecmp(prog, "VHT") == 0)
120 return PROGRAM_VHT;
121 if (strcasecmp(prog, "60GHZ") == 0)
122 return PROGRAM_60GHZ;
123 if (strcasecmp(prog, "NAN") == 0)
124 return PROGRAM_NAN;
priyadharshini gowthaman12dd4142016-06-22 22:47:14 -0700125 if (strcasecmp(prog, "LOC") == 0)
126 return PROGRAM_LOC;
priyadharshini gowthamanb4e05fc2016-10-13 15:02:35 -0700127 if (strcasecmp(prog, "MBO") == 0)
128 return PROGRAM_MBO;
Adil Saeed Musthafa33ea2872017-04-10 23:13:24 -0700129 if (strcasecmp(prog, "IoTLP") == 0)
130 return PROGRAM_IOTLP;
Jouni Malinen5c3813a2017-08-26 13:30:39 +0300131 if (strcasecmp(prog, "DPP") == 0)
132 return PROGRAM_DPP;
Ankita Bajaja2cb5672017-10-25 16:08:28 +0530133 if (strcasecmp(prog, "OCE") == 0)
134 return PROGRAM_OCE;
priyadharshini gowthaman0e209fc2018-01-26 15:15:37 -0800135 if (strcasecmp(prog, "WPA3") == 0)
136 return PROGRAM_WPA3;
Amarnath Hullur Subramanyam8f9c8682018-01-30 19:01:51 -0800137 if (strcasecmp(prog, "HE") == 0)
138 return PROGRAM_HE;
Vamsi Krishnaf642d6a2020-03-27 12:33:14 +0530139 if (strcasecmp(prog, "QM") == 0)
140 return PROGRAM_QM;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200141
142 return PROGRAM_UNKNOWN;
143}
priyadharshini gowthaman72462ef2016-06-22 22:47:14 -0700144
145
146static int parse_hex(char c)
147{
148 if (c >= '0' && c <= '9')
149 return c - '0';
150 if (c >= 'a' && c <= 'f')
151 return c - 'a' + 10;
152 if (c >= 'A' && c <= 'F')
153 return c - 'A' + 10;
154 return -1;
155}
156
157
Alexei Avshalom Lazar9a4f98d2019-05-02 13:35:22 +0300158int hex_byte(const char *str)
priyadharshini gowthaman72462ef2016-06-22 22:47:14 -0700159{
160 int res1, res2;
161
162 res1 = parse_hex(str[0]);
163 if (res1 < 0)
164 return -1;
165 res2 = parse_hex(str[1]);
166 if (res2 < 0)
167 return -1;
168 return (res1 << 4) | res2;
169}
170
171
Jouni Malinen08cf2312017-09-04 13:39:47 +0300172int parse_hexstr(const char *hex, unsigned char *buf, size_t buflen)
173{
174 size_t i;
175 const char *pos = hex;
176
177 for (i = 0; i < buflen; i++) {
178 int val;
179
180 if (*pos == '\0')
181 break;
182 val = hex_byte(pos);
183 if (val < 0)
184 return -1;
185 buf[i] = val;
186 pos += 2;
187 }
188
189 return i;
190}
191
192
priyadharshini gowthaman72462ef2016-06-22 22:47:14 -0700193int parse_mac_address(struct sigma_dut *dut, const char *arg,
194 unsigned char *addr)
195{
196 int i;
197 const char *pos = arg;
198
199 if (strlen(arg) != 17)
200 goto fail;
201
202 for (i = 0; i < ETH_ALEN; i++) {
203 int val;
204
205 val = hex_byte(pos);
206 if (val < 0)
207 goto fail;
208 addr[i] = val;
209 if (i + 1 < ETH_ALEN) {
210 pos += 2;
211 if (*pos != ':')
212 goto fail;
213 pos++;
214 }
215 }
216
217 return 0;
218
219fail:
220 sigma_dut_print(dut, DUT_MSG_ERROR,
221 "Invalid MAC address %s (expected format xx:xx:xx:xx:xx:xx)",
222 arg);
223 return -1;
224}
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700225
226
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200227int is_60g_sigma_dut(struct sigma_dut *dut)
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700228{
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200229 return dut->program == PROGRAM_60GHZ ||
230 (dut->program == PROGRAM_WPS &&
Jouni Malinen016ae6c2019-11-04 17:00:01 +0200231 (get_driver_type(dut) == DRIVER_WIL6210));
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200232}
233
234
235unsigned int channel_to_freq(struct sigma_dut *dut, unsigned int channel)
236{
237 if (is_60g_sigma_dut(dut)) {
238 if (channel >= 1 && channel <= 4)
239 return 58320 + 2160 * channel;
240
241 return 0;
242 }
243
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700244 if (channel >= 1 && channel <= 13)
245 return 2407 + 5 * channel;
246 if (channel == 14)
247 return 2484;
248 if (channel >= 36 && channel <= 165)
249 return 5000 + 5 * channel;
250
251 return 0;
252}
253
254
255unsigned int freq_to_channel(unsigned int freq)
256{
257 if (freq >= 2412 && freq <= 2472)
258 return (freq - 2407) / 5;
259 if (freq == 2484)
260 return 14;
261 if (freq >= 5180 && freq <= 5825)
262 return (freq - 5000) / 5;
Alexei Avshalom Lazar093569f2018-11-13 14:08:17 +0200263 if (freq >= 58320 && freq <= 64800)
264 return (freq - 58320) / 2160;
Rakesh Sunki7192dc42017-03-30 14:47:55 -0700265 return 0;
266}
Peng Xu769731a2017-05-10 17:27:28 -0700267
268
Peng Xu525965b2018-06-26 16:40:14 -0700269int is_ipv6_addr(const char *str)
270{
271 struct sockaddr_in6 addr;
272
273 return inet_pton(AF_INET6, str, &(addr.sin6_addr));
274}
275
276
Rakesh Sunki8f8e74b2017-05-16 15:42:12 -0700277void convert_mac_addr_to_ipv6_lladdr(u8 *mac_addr, char *ipv6_buf,
278 size_t buf_len)
279{
280 u8 temp = mac_addr[0] ^ 0x02;
281
282 snprintf(ipv6_buf, buf_len, "fe80::%02x%02x:%02xff:fe%02x:%02x%02x",
283 temp, mac_addr[1], mac_addr[2],
284 mac_addr[3], mac_addr[4], mac_addr[5]);
285}
286
287
Peng Xu8863ec72018-08-06 11:50:37 -0700288size_t convert_mac_addr_to_ipv6_linklocal(const u8 *mac_addr, u8 *ipv6)
289{
290 int i;
291
292 ipv6[0] = 0xfe;
293 ipv6[1] = 0x80;
294 for (i = 2; i < 8; i++)
295 ipv6[i] = 0;
296 ipv6[8] = mac_addr[0] ^ 0x02;
297 ipv6[9] = mac_addr[1];
298 ipv6[10] = mac_addr[2];
299 ipv6[11] = 0xff;
300 ipv6[12] = 0xfe;
301 ipv6[13] = mac_addr[3];
302 ipv6[14] = mac_addr[4];
303 ipv6[15] = mac_addr[5];
304
305 return 16;
306}
307
308
Peng Xu769731a2017-05-10 17:27:28 -0700309#ifndef ANDROID
310
311size_t strlcpy(char *dest, const char *src, size_t siz)
312{
313 const char *s = src;
314 size_t left = siz;
315
316 if (left) {
317 /* Copy string up to the maximum size of the dest buffer */
318 while (--left != 0) {
319 if ((*dest++ = *s++) == '\0')
320 break;
321 }
322 }
323
324 if (left == 0) {
325 /* Not enough room for the string; force NUL-termination */
326 if (siz != 0)
327 *dest = '\0';
328 while (*s++)
329 ; /* determine total src string length */
330 }
331
332 return s - src - 1;
333}
334
335
336size_t strlcat(char *dst, const char *str, size_t size)
337{
338 char *pos;
339 size_t dstlen, srclen, copy;
340
341 srclen = strlen(str);
342 for (pos = dst; pos - dst < size && *dst; pos++)
343 ;
344 dstlen = pos - dst;
345 if (*dst)
346 return dstlen + srclen;
347 if (dstlen + srclen + 1 > size)
348 copy = size - dstlen - 1;
349 else
350 copy = srclen;
351 memcpy(pos, str, copy);
352 pos[copy] = '\0';
353 return dstlen + srclen;
354}
355
356#endif /* ANDROID */
Ankita Bajaj1bde7942018-01-09 19:15:01 +0530357
358
359void hex_dump(struct sigma_dut *dut, u8 *data, size_t len)
360{
361 char buf[1024];
362 size_t index;
363 u8 *ptr;
364 int pos;
365
366 memset(buf, 0, sizeof(buf));
367 ptr = data;
368 pos = 0;
369 for (index = 0; index < len; index++) {
370 pos += snprintf(&(buf[pos]), sizeof(buf) - pos,
371 "%02x ", *ptr++);
372 if (pos > 1020)
373 break;
374 }
375 sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len);
376 sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf);
377}
Peng Xu291d97d2018-01-31 16:34:03 -0800378
379
380#ifdef NL80211_SUPPORT
381
382void * nl80211_cmd(struct sigma_dut *dut, struct nl80211_ctx *ctx,
383 struct nl_msg *msg, int flags, uint8_t cmd)
384{
385 return genlmsg_put(msg, 0, 0, ctx->netlink_familyid,
386 0, flags, cmd, 0);
387}
388
389
390static struct nl_msg *
391nl80211_ifindex_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx, int ifindex,
392 int flags, uint8_t cmd)
393{
394 struct nl_msg *msg;
395
396 msg = nlmsg_alloc();
397 if (!msg) {
398 sigma_dut_print(dut, DUT_MSG_ERROR,
399 "Failed to allocate NL message");
400 return NULL;
401 }
402
403 if (!nl80211_cmd(dut, ctx, msg, flags, cmd) ||
404 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
405 nlmsg_free(msg);
406 return NULL;
407 }
408
409 return msg;
410}
411
412
413struct nl_msg * nl80211_drv_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx,
414 int ifindex, int flags, uint8_t cmd)
415{
416 return nl80211_ifindex_msg(dut, ctx, ifindex, flags, cmd);
417}
418
419
420static int ack_handler(struct nl_msg *msg, void *arg)
421{
422 int *err = arg;
423 *err = 0;
424 return NL_STOP;
425}
426
427
428static int finish_handler(struct nl_msg *msg, void *arg)
429{
430 int *ret = arg;
431 *ret = 0;
432 return NL_SKIP;
433}
434
435
436static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
437 void *arg)
438{
439 int *ret = arg;
440 *ret = err->error;
441 return NL_SKIP;
442}
443
444
445int send_and_recv_msgs(struct sigma_dut *dut, struct nl80211_ctx *ctx,
446 struct nl_msg *nlmsg,
447 int (*valid_handler)(struct nl_msg *, void *),
448 void *valid_data)
449{
450 struct nl_cb *cb;
451 int err = -ENOMEM;
452
453 if (!nlmsg)
454 return -ENOMEM;
455
456 cb = nl_cb_alloc(NL_CB_DEFAULT);
457 if (!cb)
458 goto out;
459
460 err = nl_send_auto_complete(ctx->sock, nlmsg);
461 if (err < 0) {
462 sigma_dut_print(dut, DUT_MSG_ERROR,
463 "nl80211: failed to send err=%d", err);
464 goto out;
465 }
466
467 err = 1;
468
469 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
470 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
471 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
472
473 if (valid_handler)
474 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
475 valid_handler, valid_data);
476
477 while (err > 0) {
478 int res = nl_recvmsgs(ctx->sock, cb);
479
480 if (res < 0) {
481 sigma_dut_print(dut, DUT_MSG_ERROR,
482 "nl80211: %s->nl_recvmsgs failed: res=%d, err=%d",
483 __func__, res, err);
484 }
485 }
486 out:
487 nl_cb_put(cb);
488 if (!valid_handler && valid_data == (void *) -1) {
489 if (nlmsg) {
490 struct nlmsghdr *hdr = nlmsg_hdr(nlmsg);
491 void *data = nlmsg_data(hdr);
492 int len = hdr->nlmsg_len - NLMSG_HDRLEN;
493
494 memset(data, 0, len);
495 }
496 }
497
498 nlmsg_free(nlmsg);
499 return err;
500}
501
502
503struct nl80211_ctx * nl80211_init(struct sigma_dut *dut)
504{
505 struct nl80211_ctx *ctx;
506
507 ctx = calloc(1, sizeof(struct nl80211_ctx));
508 if (!ctx) {
509 sigma_dut_print(dut, DUT_MSG_ERROR,
510 "Failed to alloc nl80211_ctx");
511 return NULL;
512 }
513
514 ctx->sock = nl_socket_alloc();
515 if (!ctx->sock) {
516 sigma_dut_print(dut, DUT_MSG_ERROR,
517 "Failed to create NL socket, err: %s",
518 strerror(errno));
519 goto cleanup;
520 }
521
522 if (nl_connect(ctx->sock, NETLINK_GENERIC)) {
523 sigma_dut_print(dut, DUT_MSG_ERROR,
524 "Could not connect socket, err: %s",
525 strerror(errno));
526 goto cleanup;
527 }
528
529 if (nl_socket_set_buffer_size(ctx->sock, SOCK_BUF_SIZE, 0) < 0) {
530 sigma_dut_print(dut, DUT_MSG_INFO,
531 "Could not set nl_socket RX buffer size for sock: %s",
532 strerror(errno));
533 }
534
535 ctx->netlink_familyid = genl_ctrl_resolve(ctx->sock, "nl80211");
536 if (ctx->netlink_familyid < 0) {
537 sigma_dut_print(dut, DUT_MSG_ERROR,
538 "Could not resolve nl80211 family id");
539 goto cleanup;
540 }
541
542 ctx->nlctrl_familyid = genl_ctrl_resolve(ctx->sock, "nlctrl");
543 if (ctx->nlctrl_familyid < 0) {
544 sigma_dut_print(dut, DUT_MSG_ERROR,
545 "net link family nlctrl is not present: %d err:%s",
546 ctx->nlctrl_familyid, strerror(errno));
547 goto cleanup;
548 }
549
550 return ctx;
551
552cleanup:
553 if (ctx->sock)
554 nl_socket_free(ctx->sock);
555
556 free(ctx);
557 return NULL;
558}
559
560
561void nl80211_deinit(struct sigma_dut *dut, struct nl80211_ctx *ctx)
562{
563 if (!ctx || !ctx->sock) {
564 sigma_dut_print(dut, DUT_MSG_ERROR, "%s: ctx/sock is NULL",
565 __func__);
566 return;
567 }
568 nl_socket_free(ctx->sock);
569 free(ctx);
570}
571
572#endif /* NL80211_SUPPORT */
Alexei Avshalom Lazar64279692018-12-23 16:49:49 +0200573
574
Alexei Avshalom Lazar0dae51c2018-12-18 16:00:18 +0200575static int get_wps_pin_checksum(int pin)
576{
577 int a = 0;
578
579 while (pin > 0) {
580 a += 3 * (pin % 10);
581 pin = pin / 10;
582 a += (pin % 10);
583 pin = pin / 10;
584 }
585
586 return (10 - (a % 10)) % 10;
587}
588
589
590int get_wps_pin_from_mac(struct sigma_dut *dut, const char *macaddr,
591 char *pin, size_t len)
592{
593 unsigned char mac[ETH_ALEN];
594 int tmp, checksum;
595
596 if (len < 9)
597 return -1;
598 if (parse_mac_address(dut, macaddr, mac))
599 return -1;
600
601 /*
602 * get 7 digit PIN from the last 24 bits of MAC
603 * range 1000000 - 9999999
604 */
605 tmp = (mac[5] & 0xFF) | ((mac[4] & 0xFF) << 8) |
606 ((mac[3] & 0xFF) << 16);
607 tmp = (tmp % 9000000) + 1000000;
608 checksum = get_wps_pin_checksum(tmp);
609 snprintf(pin, len, "%07d%01d", tmp, checksum);
610 return 0;
611}
612
613
Alexei Avshalom Lazar744ae8a2019-01-31 17:26:46 +0200614int get_wps_forced_version(struct sigma_dut *dut, const char *str)
615{
616 int major, minor, result = 0;
617 int count = sscanf(str, "%d.%d", &major, &minor);
618
619 if (count == 2) {
620 result = major * 16 + minor;
621 sigma_dut_print(dut, DUT_MSG_DEBUG,
622 "Force WPS version to 0x%02x (%s)",
623 result, str);
624 } else {
625 sigma_dut_print(dut, DUT_MSG_ERROR,
626 "Invalid WPS version %s", str);
627 }
628
629 return result;
630}
631
632
Alexei Avshalom Lazar64279692018-12-23 16:49:49 +0200633void str_remove_chars(char *str, char ch)
634{
635 char *pr = str, *pw = str;
636
637 while (*pr) {
638 *pw = *pr++;
639 if (*pw != ch)
640 pw++;
641 }
642 *pw = '\0';
643}
Alexei Avshalom Lazara37dc162019-02-04 14:06:48 +0200644
645
646static const char base64_table[65] =
647 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
648
649
650int base64_encode(const char *src, size_t len, char *out, size_t out_len)
651{
652 unsigned char *pos;
653 const unsigned char *end, *in;
654 size_t olen;
655
656 olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
657 olen++; /* nul termination */
658 if (olen < len || olen > out_len)
659 return -1;
660
661 end = (unsigned char *)(src + len);
662 in = (unsigned char *)src;
663 pos = (unsigned char *)out;
664 while (end - in >= 3) {
665 *pos++ = base64_table[(in[0] >> 2) & 0x3f];
666 *pos++ = base64_table[(((in[0] & 0x03) << 4) |
667 (in[1] >> 4)) & 0x3f];
668 *pos++ = base64_table[(((in[1] & 0x0f) << 2) |
669 (in[2] >> 6)) & 0x3f];
670 *pos++ = base64_table[in[2] & 0x3f];
671 in += 3;
672 }
673
674 if (end - in) {
675 *pos++ = base64_table[(in[0] >> 2) & 0x3f];
676 if (end - in == 1) {
677 *pos++ = base64_table[((in[0] & 0x03) << 4) & 0x3f];
678 *pos++ = '=';
679 } else {
680 *pos++ = base64_table[(((in[0] & 0x03) << 4) |
681 (in[1] >> 4)) & 0x3f];
682 *pos++ = base64_table[((in[1] & 0x0f) << 2) & 0x3f];
683 }
684 *pos++ = '=';
685 }
686
687 *pos = '\0';
688 return 0;
689}
690
691
692int random_get_bytes(char *buf, size_t len)
693{
694 FILE *f;
695 size_t rc;
696
697 f = fopen("/dev/urandom", "rb");
698 if (!f)
699 return -1;
700
701 rc = fread(buf, 1, len, f);
702 fclose(f);
703
704 return rc != len ? -1 : 0;
705}
Jouni Malinen3c740ab2019-10-10 15:55:11 +0300706
707
708int get_enable_disable(const char *val)
709{
710 if (strcasecmp(val, "enable") == 0 ||
711 strcasecmp(val, "enabled") == 0 ||
712 strcasecmp(val, "on") == 0 ||
713 strcasecmp(val, "yes") == 0)
714 return 1;
715 return atoi(val);
716}
Vinita Maloo54b78cf2020-03-30 12:18:19 +0530717
718
719int wcn_driver_cmd(const char *ifname, char *buf)
720{
721 int s, res;
722 size_t buf_len;
723 struct wcn_drv_priv_cmd priv_cmd;
724 struct ifreq ifr;
725
726 s = socket(PF_INET, SOCK_DGRAM, 0);
727 if (s < 0) {
728 perror("socket");
729 return -1;
730 }
731
732 memset(&ifr, 0, sizeof(ifr));
733 memset(&priv_cmd, 0, sizeof(priv_cmd));
734 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
735 buf_len = strlen(buf);
736 priv_cmd.buf = buf;
737 priv_cmd.used_len = buf_len;
738 priv_cmd.total_len = buf_len;
739 ifr.ifr_data = (void *) &priv_cmd;
740 res = ioctl(s, SIOCDEVPRIVATE + 1, &ifr);
741 close(s);
742 return res;
743}