1/*
2 * Wireless network adapter utilities (linux-specific)
3 *
4 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $Id: wl_bsd.c 327541 2012-04-14 00:40:20Z $
19 */
20
21#include <stdio.h>
22#include <unistd.h>
23#include <string.h>
24#include <errno.h>
25#include <sys/ioctl.h>
26#include <net/if.h>
27#include <sys/types.h>
28
29typedef u_int64_t u64;
30typedef u_int32_t u32;
31typedef u_int16_t u16;
32typedef u_int8_t u8;
33
34#include <typedefs.h>
35#include <wlioctl.h>
36#include <wlutils.h>
37#include <shutils.h>
38
39
40int
41wl_ioctl(char *name, int cmd, void *buf, int len)
42{
43	struct ifreq ifr;
44	wl_ioctl_t ioc;
45	int ret = 0;
46	int s;
47	char nv_name[IFNAMSIZ], bwl_name[IFNAMSIZ];
48	int unit;
49
50	if (osifname_to_nvifname(name, nv_name, sizeof(nv_name)) != 0)
51		return -1;
52
53	/* NVRAM I/F names for wireless devices are always wlX or wlX.Y */
54	if (strncmp(nv_name, "wl", 2))
55		return -1;
56
57	if (get_ifname_unit(nv_name, &unit, NULL) != 0)
58		return -1;
59	snprintf(bwl_name, IFNAMSIZ, "bwl%d", unit);
60
61	/* open socket to kernel */
62	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
63		perror("socket");
64		return errno;
65	}
66
67	/* do it */
68	ioc.cmd = cmd;
69	ioc.buf = buf;
70	ioc.len = len;
71
72	/* initializing the remaining fields */
73	ioc.set = FALSE;
74	ioc.used = 0;
75	ioc.needed = 0;
76
77	/* strncpy(ifr.ifr_name, name, IFNAMSIZ); */
78	strncpy(ifr.ifr_name, bwl_name, IFNAMSIZ);
79	ifr.ifr_data = (caddr_t) &ioc;
80	if ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0) {
81		/* cprintf("%s: cmd=%d\n", __func__, cmd); */
82		if (cmd != WLC_GET_MAGIC)
83			perror(ifr.ifr_name);
84	}
85
86	/* cleanup */
87	close(s);
88	/* printf("%s(%d) ret %d\n", __func__, cmd, ret); */
89	return ret;
90}
91
92
93int
94wl_hwaddr(char *name, unsigned char *hwaddr)
95{
96	struct ifreq ifr;
97	int ret = 0;
98	int s;
99
100	/* open socket to kernel */
101	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
102		perror("socket");
103		return errno;
104	}
105
106	/* do it */
107	strncpy(ifr.ifr_name, name, IFNAMSIZ);
108	if ((ret = ioctl(s, SIOCGIFHWADDR, &ifr)) == 0)
109		memcpy(hwaddr, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN);
110
111	/* cleanup */
112	close(s);
113	return ret;
114}
115