GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / et / linux / et.c
blobcc23dd6347d75195a87e79452cd20c520560e7d6
1 /*
2 * et driver ioctl swiss army knife command.
4 * Copyright (C) 2012, 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.
18 * $Id: et.c 393340 2013-03-27 06:10:49Z $
21 #include <stdio.h>
23 #include <sys/param.h>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
26 #include <sys/sysctl.h>
27 #include <sys/time.h>
28 #include <net/if.h>
29 #include <netinet/in.h>
30 #include <typedefs.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <etioctl.h>
36 #include <proto/ethernet.h>
38 typedef u_int64_t u64;
39 typedef u_int32_t u32;
40 typedef u_int16_t u16;
41 typedef u_int8_t u8;
42 #include <linux/sockios.h>
43 #include <linux/ethtool.h>
45 static void usage(char *av0);
46 static void syserr(char *s);
47 static void et_find(int s, struct ifreq *ifr);
48 static int et_check(int s, struct ifreq *ifr);
52 char buf[16 * 1024];
54 #define VECLEN 5
56 int
57 main(int ac, char *av[])
59 char *interface = NULL;
60 struct ifreq ifr;
61 char *endptr;
62 int arg;
63 int vecarg[VECLEN];
64 int s;
65 static int optind;
66 et_var_t var;
68 if (ac < 2)
69 usage(av[0]);
71 optind = 1;
73 if (av[1][0] == '-') {
74 if ((av[1][1] != 'a') && (av[1][1] != 'i'))
75 usage(av[0]);
76 if (ac < 4)
77 usage(av[0]);
78 interface = av[2];
79 optind += 2;
82 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
83 syserr("socket");
85 if (interface)
86 strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name));
87 else
88 et_find(s, &ifr);
90 if (!*ifr.ifr_name) {
91 fprintf(stderr, "et interface not found\n");
92 exit(1);
95 if (strcmp(av[optind], "up") == 0) {
96 if (ioctl(s, SIOCSETCUP, (caddr_t)&ifr) < 0)
97 syserr("etcup");
98 } else if (strcmp(av[optind], "down") == 0) {
99 if (ioctl(s, SIOCSETCDOWN, (caddr_t)&ifr) < 0)
100 syserr("etcdown");
101 } else if (strcmp(av[optind], "loop") == 0) {
102 if (optind >= (ac -1))
103 usage(av[0]);
104 arg = atoi(av[optind + 1]);
105 ifr.ifr_data = (caddr_t) &arg;
106 if (ioctl(s, SIOCSETCLOOP, (caddr_t)&ifr) < 0)
107 syserr("etcloop");
108 } else if ((strcmp(av[optind], "dump") == 0) && (ac == 2)) {
109 ifr.ifr_data = buf;
110 if (ioctl(s, SIOCGETCDUMP, (caddr_t)&ifr) < 0)
111 syserr("etcdump");
112 printf("%s\n", buf);
113 } else if (strcmp(av[optind], "msglevel") == 0) {
114 if (optind >= (ac -1))
115 usage(av[0]);
116 arg = strtol(av[optind + 1], &endptr, 0);
117 ifr.ifr_data = (caddr_t) &arg;
118 if (ioctl(s, SIOCSETCSETMSGLEVEL, (caddr_t)&ifr) < 0)
119 syserr("etcsetmsglevel");
120 } else if (strcmp(av[optind], "promisc") == 0) {
121 if (optind >= (ac -1))
122 usage(av[0]);
123 arg = atoi(av[optind + 1]);
124 ifr.ifr_data = (caddr_t) &arg;
125 if (ioctl(s, SIOCSETCPROMISC, (caddr_t)&ifr) < 0)
126 syserr("etcpromisc");
127 } else if (strcmp(av[optind], "qos") == 0) {
128 if (optind >= (ac -1))
129 usage(av[0]);
130 arg = atoi(av[optind + 1]);
131 ifr.ifr_data = (caddr_t) &arg;
132 if (ioctl(s, SIOCSETCQOS, (caddr_t)&ifr) < 0)
133 syserr("etcqos");
134 } else if (strcmp(av[optind], "speed") == 0) {
135 if (optind >= (ac -1))
136 usage(av[0]);
137 if (strcmp(av[optind+1], "auto") == 0)
138 arg = -1;
139 else if (strcmp(av[optind+1], "10half") == 0)
140 arg = 0;
141 else if (strcmp(av[optind+1], "10full") == 0)
142 arg = 1;
143 else if (strcmp(av[optind+1], "100half") == 0)
144 arg = 2;
145 else if (strcmp(av[optind+1], "100full") == 0)
146 arg = 3;
147 else if (strcmp(av[optind+1], "1000full") == 0)
148 arg = 5;
149 else
150 usage(av[0]);
152 ifr.ifr_data = (caddr_t) &arg;
153 if (ioctl(s, SIOCSETCSPEED, (caddr_t)&ifr) < 0)
154 syserr("etcspeed");
156 else if (strcmp(av[optind], "phyrd") == 0) {
157 int cmd = -1;
159 if ((ac < (optind + 2)) || (ac > (optind + 3))) {
160 usage(av[0]);
161 } else if (ac == (optind + 3)) {
162 /* PHY address provided */
163 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
164 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
165 cmd = SIOCGETCPHYRD2;
166 } else {
167 /* "My" PHY address implied */
168 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
169 cmd = SIOCGETCPHYRD;
171 ifr.ifr_data = (caddr_t) vecarg;
172 if (ioctl(s, cmd, (caddr_t)&ifr) < 0)
173 syserr("etcphyrd");
175 printf("0x%04x\n", vecarg[1]);
176 } else if (strcmp(av[optind], "phywr") == 0) {
177 int cmd = -1;
179 if ((ac < (optind + 3)) || (ac > (optind + 4))) {
180 usage(av[0]);
181 } else if (ac == (optind + 4)) {
182 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
183 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
184 vecarg[1] = strtoul(av[optind + 3], NULL, 0);
185 cmd = SIOCSETCPHYWR2;
186 } else {
187 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
188 vecarg[1] = strtoul(av[optind + 2], NULL, 0);
189 cmd = SIOCSETCPHYWR;
191 ifr.ifr_data = (caddr_t) vecarg;
192 if (ioctl(s, cmd, (caddr_t)&ifr) < 0)
193 syserr("etcphywr");
194 } else if (strcmp(av[optind], "robord") == 0) {
195 if (ac != (optind + 3))
196 usage(av[0]);
198 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
199 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
201 ifr.ifr_data = (caddr_t) vecarg;
202 if (ioctl(s, SIOCGETCROBORD, (caddr_t)&ifr) < 0)
203 syserr("etcrobord");
205 printf("0x%08x\n", vecarg[1]);
206 } else if (strcmp(av[optind], "robowr") == 0) {
207 if (ac != (optind + 4))
208 usage(av[0]);
210 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;;
211 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff;
212 vecarg[1] = strtoul(av[optind + 3], NULL, 0);
214 ifr.ifr_data = (caddr_t) vecarg;
215 if (ioctl(s, SIOCSETCROBOWR, (caddr_t)&ifr) < 0)
216 syserr("etcrobowr");
217 } else if (strcmp(av[optind], "clear_dump") == 0) {
218 if ((ac > (optind + 2)))
219 usage(av[0]);
221 var.set = 1;
222 var.cmd = IOV_ET_CLEAR_DUMP;
223 var.buf = NULL;
224 ifr.ifr_data = (caddr_t) &var;
225 if (ioctl(s, SIOCSETGETVAR, (caddr_t)&ifr) < 0)
226 syserr("etccleardump");
227 } else if ((strcmp(av[optind], "pktc") == 0) ||
228 (strcmp(av[optind], "pktcbnd") == 0)) {
229 /* Get pktc or pktcbnd */
230 if (ac == (optind + 1))
231 var.set = 0;
232 else {
233 var.set = 1;
234 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
236 var.len = sizeof(int);
237 var.cmd = strcmp(av[optind], "pktc") == 0 ? IOV_PKTC : IOV_PKTCBND;
238 var.buf = &vecarg;
240 ifr.ifr_data = (caddr_t)&var;
241 if (ioctl(s, SIOCSETGETVAR, (caddr_t)&ifr) < 0)
242 syserr("pktc");
244 if (!var.set)
245 printf("%d\n", vecarg[0]);
246 } else if ((strcmp(av[optind], "counters") == 0)) {
247 if (ac == (optind + 1))
248 var.set = 0;
249 else
250 syserr("counters");
252 var.cmd = IOV_COUNTERS;
253 var.buf = buf;
254 var.len = sizeof(buf);
256 ifr.ifr_data = (caddr_t)&var;
257 if (ioctl(s, SIOCSETGETVAR, (caddr_t)&ifr) < 0)
258 syserr("counters");
260 printf("%s\n", buf);
261 } else if ((strcmp(av[optind], "dump") == 0) && (ac > 2)) {
262 if (strcmp(av[optind + 1], "ctf") == 0) {
263 if (ac == (optind + 2))
264 var.set = 0;
265 else
266 syserr("dump ctf");
268 var.cmd = IOV_DUMP_CTF;
269 var.buf = buf;
270 var.len = sizeof(buf);
272 ifr.ifr_data = (caddr_t)&var;
273 if (ioctl(s, SIOCSETGETVAR, (caddr_t)&ifr) < 0)
274 syserr("dump ctf");
276 printf("%s\n", buf);
277 } else if (strcmp(av[optind + 1], "ctrace") == 0) {
278 if (ac == (optind + 2))
279 var.set = 0;
280 else
281 syserr("dump ctrace");
283 var.cmd = IOV_DUMP_CTRACE;
284 var.buf = buf;
285 var.len = sizeof(buf);
287 ifr.ifr_data = (caddr_t)&var;
288 if (ioctl(s, SIOCSETGETVAR, (caddr_t)&ifr) < 0)
289 syserr("dump ctrace");
291 printf("%s\n", buf);
293 } else {
294 if (strcmp(av[optind], "switch_mode") == 0) {
295 int all = 0;
297 /* GET case */
298 if (ac == (optind + 1)) {
299 var.set = 0;
300 vecarg[0] = VECLEN;
301 all = 1;
302 } else if (ac == (optind + 2)) {
303 var.set = 0;
304 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
305 all = (int)(vecarg[0] == VECLEN);
306 } else {
307 if (ac != (optind + 3))
308 usage(av[0]);
310 vecarg[0] = strtoul(av[optind + 1], NULL, 0);
311 vecarg[1] = strtoul(av[optind + 2], NULL, 0);
312 if (vecarg[1] > 3)
313 usage(av[0]);
315 var.set = 1;
318 var.len = VECLEN * sizeof(int);
319 var.cmd = IOV_ET_POWER_SAVE_MODE;
320 var.buf = &vecarg;
322 ifr.ifr_data = (caddr_t) &var;
323 if (ioctl(s, SIOCSETGETVAR, (caddr_t)&ifr) < 0)
324 syserr("etcswitchmode");
326 if (!var.set) {
327 if (all)
328 printf("phy power save mode for all phys:"
329 " %d %d %d %d %d \n",
330 vecarg[0], vecarg[1], vecarg[2],
331 vecarg[3], vecarg[4]);
332 else
333 printf("phy power save mode for phy %d mode %d\n",
334 vecarg[0], vecarg[1]);
336 } else {
337 usage(av[0]);
341 return (0);
344 static void
345 usage(char *av0)
347 fprintf(stderr, "usage: %s [ [ -a | -i ] interface ] and one of:\n"
348 "\tup\n"
349 "\tdown\n"
350 "\tloop <0 or 1>\n"
351 "\tdump\n"
352 "\tclear_dump\n"
353 "\tmsglevel <bitvec> (error=1, trace=2, prhdr=4, prpkt=8)\n"
354 "\tpromisc <0 or 1>\n"
355 "\tqos <0 or 1>\n"
356 "\tspeed <auto, 10half, 10full, 100half, 100full, 1000full>\n"
357 "\tphyrd [<phyaddr>] <reg>\n"
358 "\tphywr [<phyaddr>] <reg> <val>\n"
359 "\trobord <page> <reg>\n"
360 "\trobowr <page> <reg> <val>\n"
361 "\tswitch_mode <phy> <mode> (mode normal=0, auto=1, manual=2, both=3)\n"
362 "\tpktc <0 or 1>\n"
363 "\tpktcbnd <val>\n"
365 av0);
366 exit(1);
369 static void
370 et_find(int s, struct ifreq *ifr)
372 char proc_net_dev[] = "/proc/net/dev";
373 FILE *fp;
374 char buf[512], *c, *name;
376 ifr->ifr_name[0] = '\0';
378 /* eat first two lines */
379 if (!(fp = fopen(proc_net_dev, "r")) ||
380 !fgets(buf, sizeof(buf), fp) ||
381 !fgets(buf, sizeof(buf), fp))
382 return;
384 while (fgets(buf, sizeof(buf), fp)) {
385 c = buf;
386 while (isspace(*c))
387 c++;
388 if (!(name = strsep(&c, ":")))
389 continue;
390 strncpy(ifr->ifr_name, name, IFNAMSIZ);
391 if (et_check(s, ifr) == 0)
392 break;
393 ifr->ifr_name[0] = '\0';
396 fclose(fp);
399 static int
400 et_check(int s, struct ifreq *ifr)
402 struct ethtool_drvinfo info;
404 memset(&info, 0, sizeof(info));
405 info.cmd = ETHTOOL_GDRVINFO;
406 ifr->ifr_data = (caddr_t)&info;
407 if (ioctl(s, SIOCETHTOOL, (caddr_t)ifr) < 0) {
408 /* print a good diagnostic if not superuser */
409 if (errno == EPERM)
410 syserr("siocethtool");
411 return (-1);
414 if (!strncmp(info.driver, "et", 2))
415 return (0);
416 else if (!strncmp(info.driver, "bcm57", 5))
417 return (0);
419 return (-1);
422 static void
423 syserr(char *s)
425 perror(s);
426 exit(1);