Add PPTP runtime and GUI
[tomato.git] / release / src / router / et / et.c
blob0b0e1e8f791103869a911575f31e30a1550fafec
1 /*
2 * et driver ioctl swiss army knife command.
4 * Copyright (C) 2009, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
12 * $Id: et.c,v 1.9.130.4 2009/07/17 03:09:33 Exp $
15 #include <stdio.h>
17 #include <sys/param.h>
18 #include <sys/ioctl.h>
19 #include <sys/socket.h>
20 #include <sys/sysctl.h>
21 #include <sys/time.h>
22 #include <net/if.h>
23 #include <netinet/in.h>
24 #include <typedefs.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <etioctl.h>
30 #include <proto/ethernet.h>
32 typedef u_int64_t u64;
33 typedef u_int32_t u32;
34 typedef u_int16_t u16;
35 typedef u_int8_t u8;
36 #include <linux/types.h>
37 #include <linux/sockios.h>
38 #include <linux/ethtool.h>
40 static void usage(char *av0);
41 static void syserr(char *s);
42 static void et_find(int s, struct ifreq *ifr);
43 static int et_check(int s, struct ifreq *ifr);
47 char buf[16 * 1024];
49 #define VECLEN 5
51 int
52 main(int ac, char *av[])
54 char *interface = NULL;
55 struct ifreq ifr;
56 char *endptr;
57 int arg;
58 int vecarg[VECLEN];
59 int s;
60 static int optind;
62 if (ac < 2)
63 usage(av[0]);
65 optind = 1;
67 if (av[1][0] == '-') {
68 if ((av[1][1] != 'a') && (av[1][1] != 'i'))
69 usage(av[0]);
70 if (ac < 4)
71 usage(av[0]);
72 interface = av[2];
73 optind += 2;
76 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
77 syserr("socket");
79 if (interface)
80 strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name));
81 else
82 et_find(s, &ifr);
84 if (!*ifr.ifr_name) {
85 fprintf(stderr, "et interface not found\n");
86 exit(1);
89 if (strcmp(av[optind], "up") == 0) {
90 if (ioctl(s, SIOCSETCUP, (caddr_t)&ifr) < 0)
91 syserr("etcup");
92 } else if (strcmp(av[optind], "down") == 0) {
93 if (ioctl(s, SIOCSETCDOWN, (caddr_t)&ifr) < 0)
94 syserr("etcdown");
95 } else if (strcmp(av[optind], "loop") == 0) {
96 if (optind >= (ac -1))
97 usage(av[0]);
98 arg = atoi(av[optind + 1]);
99 ifr.ifr_data = (caddr_t) &arg;
100 if (ioctl(s, SIOCSETCLOOP, (caddr_t)&ifr) < 0)
101 syserr("etcloop");
102 } else if (strcmp(av[optind], "dump") == 0) {
103 ifr.ifr_data = buf;
104 if (ioctl(s, SIOCGETCDUMP, (caddr_t)&ifr) < 0)
105 syserr("etcdump");
106 printf("%s\n", buf);
107 } else if (strcmp(av[optind], "msglevel") == 0) {
108 if (optind >= (ac -1))
109 usage(av[0]);
110 arg = strtol(av[optind + 1], &endptr, 0);
111 ifr.ifr_data = (caddr_t) &arg;
112 if (ioctl(s, SIOCSETCSETMSGLEVEL, (caddr_t)&ifr) < 0)
113 syserr("etcsetmsglevel");
114 } else if (strcmp(av[optind], "promisc") == 0) {
115 if (optind >= (ac -1))
116 usage(av[0]);
117 arg = atoi(av[optind + 1]);
118 ifr.ifr_data = (caddr_t) &arg;
119 if (ioctl(s, SIOCSETCPROMISC, (caddr_t)&ifr) < 0)
120 syserr("etcpromisc");
121 } else if (strcmp(av[optind], "qos") == 0) {
122 if (optind >= (ac -1))
123 usage(av[0]);
124 arg = atoi(av[optind + 1]);
125 ifr.ifr_data = (caddr_t) &arg;
126 if (ioctl(s, SIOCSETCQOS, (caddr_t)&ifr) < 0)
127 syserr("etcqos");
128 } else if (strcmp(av[optind], "speed") == 0) {
129 if (optind >= (ac -1))
130 usage(av[0]);
131 if (strcmp(av[optind+1], "auto") == 0)
132 arg = -1;
133 else if (strcmp(av[optind+1], "10half") == 0)
134 arg = 0;
135 else if (strcmp(av[optind+1], "10full") == 0)
136 arg = 1;
137 else if (strcmp(av[optind+1], "100half") == 0)
138 arg = 2;
139 else if (strcmp(av[optind+1], "100full") == 0)
140 arg = 3;
141 else if (strcmp(av[optind+1], "1000full") == 0)
142 arg = 5;
143 else
144 usage(av[0]);
146 ifr.ifr_data = (caddr_t) &arg;
147 if (ioctl(s, SIOCSETCSPEED, (caddr_t)&ifr) < 0)
148 syserr("etcspeed");
150 else if (strcmp(av[optind], "phyrd") == 0) {
151 int cmd = -1;
153 if ((ac < (optind + 2)) || (ac > (optind + 3))) {
154 usage(av[0]);
155 } else if (ac == (optind + 3)) {
156 /* PHY address provided */
157 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
158 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
159 cmd = SIOCGETCPHYRD2;
160 } else {
161 /* "My" PHY address implied */
162 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
163 cmd = SIOCGETCPHYRD;
165 ifr.ifr_data = (caddr_t) vecarg;
166 if (ioctl(s, cmd, (caddr_t)&ifr) < 0)
167 syserr("etcphyrd");
169 printf("0x%04x\n", vecarg[1]);
170 } else if (strcmp(av[optind], "phywr") == 0) {
171 int cmd = -1;
173 if ((ac < (optind + 3)) || (ac > (optind + 4))) {
174 usage(av[0]);
175 } else if (ac == (optind + 4)) {
176 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
177 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
178 vecarg[1] = strtoul(av[optind + 3], NULL, 0);
179 cmd = SIOCSETCPHYWR2;
180 } else {
181 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
182 vecarg[1] = strtoul(av[optind + 2], NULL, 0);
183 cmd = SIOCSETCPHYWR;
185 ifr.ifr_data = (caddr_t) vecarg;
186 if (ioctl(s, cmd, (caddr_t)&ifr) < 0)
187 syserr("etcphywr");
188 } else if (strcmp(av[optind], "robord") == 0) {
189 if (ac != (optind + 3))
190 usage(av[0]);
192 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
193 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
195 ifr.ifr_data = (caddr_t) vecarg;
196 if (ioctl(s, SIOCGETCROBORD, (caddr_t)&ifr) < 0)
197 syserr("etcrobord");
199 printf("0x%04x\n", vecarg[1]);
200 } else if (strcmp(av[optind], "robowr") == 0) {
201 if (ac != (optind + 4))
202 usage(av[0]);
204 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
205 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
206 vecarg[1] = strtoul(av[optind + 3], NULL, 0);
208 ifr.ifr_data = (caddr_t) vecarg;
209 if (ioctl(s, SIOCSETCROBOWR, (caddr_t)&ifr) < 0)
210 syserr("etcrobowr");
211 } else {
212 #ifdef IOV_ET_POWER_SAVE_MODE
213 if (strcmp(av[optind], "switch_mode") == 0) {
214 int all = 0;
215 et_var_t var;
217 /* GET case */
218 if (ac == (optind + 1)) {
219 var.set = 0;
220 vecarg[0] = VECLEN;
221 all = 1;
222 } else if (ac == (optind + 2)) {
223 var.set = 0;
224 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
225 all = (int)(vecarg[0] == VECLEN);
226 } else {
227 if (ac != (optind + 3))
228 usage(av[0]);
230 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
231 vecarg[1] = strtoul(av[optind + 2], NULL, 0);
232 if (vecarg[1] > 3)
233 usage(av[0]);
235 var.set = 1;
238 var.len = VECLEN * sizeof(int);
239 var.cmd = IOV_ET_POWER_SAVE_MODE;
240 var.buf = &vecarg;
242 ifr.ifr_data = (caddr_t) &var;
243 if (ioctl(s, SIOCSETGETVAR, (caddr_t)&ifr) < 0)
244 syserr("etcswitchmode");
246 if (!var.set) {
247 if (all)
248 printf("phy power save mode for all phys:"
249 " %d %d %d %d %d \n",
250 vecarg[0], vecarg[1], vecarg[2],
251 vecarg[3], vecarg[4]);
252 else
253 printf("phy power save mode for phy %d mode %d\n",
254 vecarg[0], vecarg[1]);
256 } else
257 #endif // IOV_ET_POWER_SAVE_MODE
259 usage(av[0]);
263 return (0);
266 static void
267 usage(char *av0)
269 fprintf(stderr, "usage: %s [ [ -a | -i ] interface ] and one of:\n"
270 "\tup\n"
271 "\tdown\n"
272 "\tloop <0 or 1>\n"
273 "\tdump\n"
274 "\tmsglevel <bitvec> (error=1, trace=2, prhdr=4, prpkt=8)\n"
275 "\tpromisc <0 or 1>\n"
276 "\tqos <0 or 1>\n"
277 "\tspeed <auto, 10half, 10full, 100half, 100full, 1000full>\n"
278 "\tphyrd [<phyaddr>] <reg>\n"
279 "\tphywr [<phyaddr>] <reg> <val>\n"
280 "\trobord <page> <reg>\n"
281 "\trobowr <page> <reg> <val>\n"
282 #ifdef IOV_ET_POWER_SAVE_MODE
283 "\tswitch_mode <phy> <mode> (mode 0, 1, 2, 3)\n"
284 #endif
286 av0);
287 exit(1);
290 static void
291 et_find(int s, struct ifreq *ifr)
293 char proc_net_dev[] = "/proc/net/dev";
294 FILE *fp;
295 char buf[512], *c, *name;
297 ifr->ifr_name[0] = '\0';
299 /* eat first two lines */
300 if (!(fp = fopen(proc_net_dev, "r")) ||
301 !fgets(buf, sizeof(buf), fp) ||
302 !fgets(buf, sizeof(buf), fp))
303 return;
305 while (fgets(buf, sizeof(buf), fp)) {
306 c = buf;
307 while (isspace(*c))
308 c++;
309 if (!(name = strsep(&c, ":")))
310 continue;
311 strncpy(ifr->ifr_name, name, IFNAMSIZ);
312 if (et_check(s, ifr) == 0)
313 break;
314 ifr->ifr_name[0] = '\0';
317 fclose(fp);
320 static int
321 et_check(int s, struct ifreq *ifr)
323 struct ethtool_drvinfo info;
325 memset(&info, 0, sizeof(info));
326 info.cmd = ETHTOOL_GDRVINFO;
327 ifr->ifr_data = (caddr_t)&info;
328 if (ioctl(s, SIOCETHTOOL, (caddr_t)ifr) < 0) {
329 /* print a good diagnostic if not superuser */
330 if (errno == EPERM)
331 syserr("siocethtool");
332 return (-1);
335 if (!strncmp(info.driver, "et", 2))
336 return (0);
337 else if (!strncmp(info.driver, "bcm57", 5))
338 return (0);
340 return (-1);
343 static void
344 syserr(char *s)
346 perror(s);
347 exit(1);