• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Linux port of dhd command line utility, hacked from wl utility.
3  *
4  * Copyright (C) 1999-2009, Broadcom Corporation
5  *
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  *
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  *
20  *      Notwithstanding the above, under no circumstances may you combine this
21  * software in any way with any other Broadcom software provided under a license
22  * other than the GPL, without Broadcom's express prior written consent.
23  *
24  * $Id: dhdu_linux.c,v 1.3.10.2.2.3 2009/01/27 01:02:28 Exp $
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <errno.h>
33 #ifndef TARGETENV_android
34 #include <error.h>
35 #endif /* TARGETENV_android */
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
39 #include <net/if.h>
40 
41 
42 typedef u_int64_t u64;
43 typedef u_int32_t u32;
44 typedef u_int16_t u16;
45 typedef u_int8_t u8;
46 #include <linux/sockios.h>
47 #include <linux/ethtool.h>
48 
49 #include <typedefs.h>
50 #include <dhdioctl.h>
51 #include "dhdu.h"
52 
53 #define DEV_TYPE_LEN 4 /* length for devtype 'dhd' */
54 
55 static void
syserr(char * s)56 syserr(char *s)
57 {
58 	fprintf(stderr, "%s: ", dhdu_av0);
59 	perror(s);
60 	exit(errno);
61 }
62 
63 static int
dhd_ioctl(void * dhd,int cmd,void * buf,int len,bool set)64 dhd_ioctl(void *dhd, int cmd, void *buf, int len, bool set)
65 {
66 	struct ifreq *ifr = (struct ifreq *)dhd;
67 	dhd_ioctl_t ioc;
68 	int ret = 0;
69 	int s;
70 
71 	/* open socket to kernel */
72 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
73 		syserr("socket");
74 
75 	/* do it */
76 	ioc.cmd = cmd;
77 	ioc.buf = buf;
78 	ioc.len = len;
79 	ioc.set = set;
80 	ioc.driver = DHD_IOCTL_MAGIC;
81 	ifr->ifr_data = (caddr_t) &ioc;
82 	if ((ret = ioctl(s, SIOCDEVPRIVATE, ifr)) < 0) {
83 		if (cmd != DHD_GET_MAGIC) {
84 			ret = IOCTL_ERROR;
85 		}
86 	}
87 
88 	/* cleanup */
89 	close(s);
90 	return ret;
91 }
92 
93 static int
dhd_get_dev_type(char * name,void * buf,int len)94 dhd_get_dev_type(char *name, void *buf, int len)
95 {
96 	int s;
97 	int ret;
98 	struct ifreq ifr;
99 	struct ethtool_drvinfo info;
100 
101 	/* open socket to kernel */
102 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
103 		syserr("socket");
104 
105 	/* get device type */
106 	memset(&info, 0, sizeof(info));
107 	info.cmd = ETHTOOL_GDRVINFO;
108 	strcpy(info.driver, "?dhd");
109 	ifr.ifr_data = (caddr_t)&info;
110 	strncpy(ifr.ifr_name, name, IFNAMSIZ);
111 	if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
112 
113 		/* print a good diagnostic if not superuser */
114 		if (errno == EPERM)
115 			syserr("dhd_get_dev_type");
116 
117 		*(char *)buf = '\0';
118 	}
119 	else
120 		strncpy(buf, info.driver, len);
121 
122 	close(s);
123 	return ret;
124 }
125 
126 int
dhd_get(void * dhd,int cmd,void * buf,int len)127 dhd_get(void *dhd, int cmd, void *buf, int len)
128 {
129 	return dhd_ioctl(dhd, cmd, buf, len, FALSE);
130 }
131 
132 int
dhd_set(void * dhd,int cmd,void * buf,int len)133 dhd_set(void *dhd, int cmd, void *buf, int len)
134 {
135 	return dhd_ioctl(dhd, cmd, buf, len, TRUE);
136 }
137 
138 void
dhd_find(struct ifreq * ifr)139 dhd_find(struct ifreq *ifr)
140 {
141 	char proc_net_dev[] = "/proc/net/dev";
142 	FILE *fp;
143 	char buf[1000], *c, *name;
144 	char dev_type[DEV_TYPE_LEN];
145 
146 	ifr->ifr_name[0] = '\0';
147 
148 	/* eat first two lines */
149 	if (!(fp = fopen(proc_net_dev, "r")) ||
150 	    !fgets(buf, sizeof(buf), fp) ||
151 	    !fgets(buf, sizeof(buf), fp))
152 		return;
153 
154 	while (fgets(buf, sizeof(buf), fp)) {
155 		c = buf;
156 		while (isspace(*c))
157 			c++;
158 		if (!(name = strsep(&c, ":")))
159 			continue;
160 		strncpy(ifr->ifr_name, name, IFNAMSIZ);
161 		if (dhd_get_dev_type(name, dev_type, DEV_TYPE_LEN) >= 0 &&
162 			!strncmp(dev_type, "dhd", 3))
163 			if (dhd_check((void *)ifr) == 0)
164 				break;
165 		ifr->ifr_name[0] = '\0';
166 	}
167 
168 	fclose(fp);
169 }
170 
171 int
main(int argc,char ** argv)172 main(int argc, char **argv)
173 {
174 	struct ifreq ifr;
175 	cmd_t *cmd = NULL;
176 	int err = 0;
177 	char *ifname = NULL;
178 	int help = 0;
179 	int status = CMD_DHD;
180 
181 	UNUSED_PARAMETER(argc);
182 
183 	dhdu_av0 = argv[0];
184 
185 	memset(&ifr, 0, sizeof(ifr));
186 
187 	for (++argv; *argv;) {
188 
189 		/* command option */
190 		if ((status = dhd_option(&argv, &ifname, &help)) == CMD_OPT) {
191 			if (help)
192 				break;
193 			if (ifname) {
194 				if (strlen(ifname) > IFNAMSIZ) {
195 					fprintf(stderr, "%s: interface name too long\n", dhdu_av0);
196 					break;
197 				}
198 				strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
199 			}
200 			continue;
201 		}
202 
203 		/* parse error */
204 		else if (status == CMD_ERR)
205 			break;
206 
207 		/* use default if no interface specified */
208 		if (!*ifr.ifr_name)
209 			dhd_find(&ifr);
210 		/* validate the interface */
211 		if (!*ifr.ifr_name || dhd_check((void *)&ifr)) {
212 			fprintf(stderr, "%s: dhd driver adapter not found\n", dhdu_av0);
213 			exit(1);
214 		}
215 
216 		/* search for command */
217 		for (cmd = dhd_cmds; cmd->name && strcmp(cmd->name, *argv); cmd++);
218 
219 		/* defaults to using the set_var and get_var commands */
220 		if (cmd->name == NULL)
221 			cmd = &dhd_varcmd;
222 
223 		/* do command */
224 		if (cmd->name)
225 			err = (*cmd->func)((void *)&ifr, cmd, argv);
226 		break;
227 	}
228 
229 	/* In case of COMMAND_ERROR, command has already printed an error message */
230 	if (!cmd)
231 		dhd_usage(NULL);
232 	else if (err == USAGE_ERROR)
233 		dhd_cmd_usage(cmd);
234 	else if (err == IOCTL_ERROR)
235 		dhd_printlasterror((void *)&ifr);
236 
237 	return err;
238 }
239