OSDN Git Service

Squish more warnings in pending.
[android-x86/external-toybox.git] / toys / pending / brctl.c
1 /* brctl.c - ethernet bridge control
2  *
3  * Copyright 2013 Ashwini Kumar <ak.ashwini1981@gmail.com>
4  * Copyright 2013 Kyungwan Han <asura321@gmail.com>
5  *
6  * No Standard
7
8 USE_BRCTL(NEWTOY(brctl, "<1", TOYFLAG_USR|TOYFLAG_SBIN))
9
10 config BRCTL
11   bool "brctl"
12   default n
13   help
14     usage: brctl COMMAND [BRIDGE [INTERFACE]]
15
16     Manage ethernet bridges
17
18     Commands:
19     show                  Show a list of bridges
20     addbr BRIDGE          Create BRIDGE
21     delbr BRIDGE          Delete BRIDGE
22     addif BRIDGE IFACE    Add IFACE to BRIDGE
23     delif BRIDGE IFACE    Delete IFACE from BRIDGE
24     setageing BRIDGE TIME Set ageing time
25     setfd BRIDGE TIME     Set bridge forward delay
26     sethello BRIDGE TIME  Set hello time
27     setmaxage BRIDGE TIME Set max message age
28     setpathcost BRIDGE PORT COST   Set path cost
29     setportprio BRIDGE PORT PRIO   Set port priority
30     setbridgeprio BRIDGE PRIO      Set bridge priority
31     stp BRIDGE [1/yes/on|0/no/off] STP on/off
32 */
33
34 #define FOR_brctl
35 #include "toys.h"
36 #include <linux/if_bridge.h>
37
38 GLOBALS(
39     int sockfd;
40 )
41 #define MAX_BRIDGES 1024 //same is no of ports supported
42
43 static void get_ports(char *bridge, int *indices)
44 {
45   struct ifreq ifr;                              
46   int ifindices[MAX_BRIDGES];
47   unsigned long args[4] = { BRCTL_GET_PORT_LIST,
48     (unsigned long) ifindices, MAX_BRIDGES, 0 };
49
50   memset(ifindices, 0, MAX_BRIDGES);
51   args[1] = (unsigned long)ifindices;
52   xstrncpy(ifr.ifr_name, bridge, IFNAMSIZ);
53   ifr.ifr_data = (char *)args;
54   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
55   if (indices) memcpy(indices, ifindices, sizeof(ifindices));
56 }
57
58 void get_br_info(char *bridge, struct __bridge_info *info)
59 {
60   struct ifreq ifr;
61   unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO,
62     (unsigned long) info, 0, 0 };
63
64   memset(info, 0, sizeof(*info));
65   xstrncpy(ifr.ifr_name, bridge, IFNAMSIZ);
66   ifr.ifr_data = (char *)args;
67
68   if (ioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr) < 0) {
69     perror_msg("%s: can't get info %s\n", bridge, strerror(errno));
70     return;
71   }
72 }
73
74 void br_show(char **argv)
75 {
76   struct __bridge_info info;
77   int num, cnt, i, j, ifindices[MAX_BRIDGES], pindices[MAX_BRIDGES];
78   unsigned long args[4] = { BRCTL_GET_BRIDGES,
79     (unsigned long)ifindices, MAX_BRIDGES,0 };
80   char br[IF_NAMESIZE], ifn[IF_NAMESIZE];
81
82   num = ioctl(TT.sockfd, SIOCGIFBR, args); //ret is num of bridges found
83   if (num < 0) error_exit("get bridges fail");
84   printf("bridge name\tbridge id\t\tSTP enabled\tinterfaces\n");
85
86   for (i = 0; i < num; i++) {
87     unsigned char *id;
88
89     if (!if_indextoname(ifindices[i], br)) perror_exit("interface not found");
90     get_br_info(br, &info);
91     id = (unsigned char*)&(info.bridge_id);
92     printf("%s\t\t",br);
93     printf("%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x", id[0], id[1], 
94         id[2], id[3], id[4], id[5], id[6], id[7]);
95     printf("\t%s\t\t",(info.stp_enabled)?"yes" : "no");
96
97     memset(pindices, 0, sizeof(pindices));
98     get_ports(br, pindices);
99     for (j = 0, cnt = 0; j < MAX_BRIDGES; j++) {
100       if (!pindices[j]) continue;
101       if (!if_indextoname(pindices[j], ifn)) {
102         error_msg("no name for index :%d", pindices[j]);
103         continue;
104       }
105       if (cnt) printf("\n\t\t\t\t\t\t\t");
106       printf("%s", ifn);
107       cnt++;
108     }
109     xputc('\n');
110   }
111 }
112
113 void br_addbr(char **argv)
114 {
115   char br[IFNAMSIZ];                
116   unsigned long args[4] = {BRCTL_ADD_BRIDGE, (unsigned long) br, 0, 0};
117
118 #ifdef SIOCBRADDBR
119   xioctl(TT.sockfd, SIOCBRADDBR, argv[0]);
120 #else            
121   xstrncpy(br, argv[0], IFNAMSIZ);   
122   xioctl(TT.sockfd, SIOCSIFBR, args);
123 #endif
124 }
125
126 void br_delbr(char **argv)
127 {
128   char br[IFNAMSIZ];
129   unsigned long args[4] = {BRCTL_DEL_BRIDGE, (unsigned long) br, 0, 0};
130
131 #ifdef SIOCBRDELBR
132   xioctl(TT.sockfd, SIOCBRDELBR, argv[0]);
133 #else
134   xstrncpy(br, argv[0], IFNAMSIZ);
135   xioctl(TT.sockfd, SIOCSIFBR, args);
136 #endif
137 }
138
139 void br_addif(char **argv)
140 {
141   int index;
142   struct ifreq ifr;
143   unsigned long args[4] = {BRCTL_ADD_IF, 0, 0, 0};
144
145   if (!(index = if_nametoindex(argv[1]))) perror_exit("interface %s", argv[1]);
146 #ifdef SIOCBRADDIF
147   ifr.ifr_ifindex = index;
148   xioctl(TT.sockfd, SIOCBRADDIF, &ifr);
149 #else
150   args[1] = index;
151   xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
152   ifr.ifr_data = (char *)args;
153   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
154 #endif
155 }
156
157 void br_delif(char **argv)
158 {
159   int index;                             
160   struct ifreq ifr;                      
161   unsigned long args[4] = {BRCTL_DEL_IF, 0, 0, 0};
162
163   if (!(index = if_nametoindex(argv[1]))) perror_exit("interface %s",argv[1]);
164 #ifdef SIOCBRDELIF
165   ifr.ifr_ifindex = ifindex;
166   xioctl(TT.sockfd, SIOCBRDELIF, &ifr);
167 #else
168   args[1] = index;     
169   xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
170   ifr.ifr_data = (char *)args;  
171   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
172 #endif
173 }
174
175 static void strtotimeval(struct timeval *tv, char *time)
176 {
177   double secs;
178
179   if (sscanf(time, "%lf", &secs) != 1) error_exit("time format not proper");
180   tv->tv_sec = secs;
181   tv->tv_usec = 1000000 * (secs - tv->tv_sec);
182 }
183
184 static unsigned long tv_to_jify(struct timeval *tv)
185 {                       
186   unsigned long long jify;
187
188   jify = 1000000ULL * tv->tv_sec + tv->tv_usec;
189   return (jify/10000);
190 }                  
191
192 void set_time(char *br, unsigned long cmd, unsigned long val)
193 {
194   struct ifreq ifr;
195   unsigned long args[4] = {cmd, val, 0, 0};
196
197   xstrncpy(ifr.ifr_name, br, IFNAMSIZ);
198   ifr.ifr_data = (char *)args;
199   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
200 }
201
202 void br_set_ageing_time(char **argv)     
203 {
204   struct timeval tv;
205
206   strtotimeval(&tv, argv[1]);
207   set_time(argv[0], BRCTL_SET_AGEING_TIME, tv_to_jify(&tv));
208 }
209
210 void br_set_fwd_delay(char **argv)
211 {
212   struct timeval tv;
213
214   strtotimeval(&tv, argv[1]);
215   set_time(argv[0], BRCTL_SET_BRIDGE_FORWARD_DELAY, tv_to_jify(&tv));
216 }
217
218 void br_set_hello_time(char **argv)
219 {
220   struct timeval tv;                        
221
222   strtotimeval(&tv, argv[1]);               
223   set_time(argv[0], BRCTL_SET_BRIDGE_HELLO_TIME, tv_to_jify(&tv));
224 }
225
226 void br_set_max_age(char **argv)
227 {
228   struct timeval tv;                        
229
230   strtotimeval(&tv, argv[1]);               
231   set_time(argv[0], BRCTL_SET_BRIDGE_MAX_AGE, tv_to_jify(&tv));
232 }
233
234 void br_set_bridge_prio(char **argv)
235 {
236   int prio;
237
238   if (sscanf(argv[1], "%i", &prio) != 1) error_exit("prio not proper");
239   set_time(argv[0], BRCTL_SET_BRIDGE_PRIORITY, prio);
240 }
241
242 void br_set_stp(char **argv)
243 {
244   int i;
245   struct stp {
246     char *n;
247     int set;
248   } ss[] = {{"1", 1}, {"yes", 1},{"on", 1},
249     {"0", 0}, {"no", 0},{"off", 0}};
250
251   for (i = 0; i < ARRAY_LEN(ss); i++) {
252     if (!strcmp(ss[i].n, argv[1])) break;
253   }
254   if (i >= ARRAY_LEN(ss)) error_exit("invalid stp state");
255   set_time(argv[0], BRCTL_SET_BRIDGE_STP_STATE, ss[i].set);
256 }
257
258 void set_cost_prio(char *br, char *port, unsigned long cmd, unsigned long val)
259 {
260   struct ifreq ifr;
261   int i, index, pindices[MAX_BRIDGES];
262   unsigned long args[4] = {cmd, 0, val, 0};
263   
264   if (!(index = if_nametoindex(port))) error_exit("invalid port");
265   
266   memset(pindices, 0, sizeof(pindices));
267   get_ports(br, pindices);
268   for (i = 0; i < MAX_BRIDGES; i++) {
269     if (index == pindices[i]) break;
270   }
271   if (i >= MAX_BRIDGES) error_exit("%s not in bridge", port);
272   args[1] = i;
273   xstrncpy(ifr.ifr_name, br, IFNAMSIZ);
274   ifr.ifr_data = (char *)args;
275   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
276 }
277
278 void br_set_path_cost(char **argv)
279 {
280   int cost;
281
282   cost = atolx_range(argv[2], 0, INT_MAX);
283   set_cost_prio(argv[0], argv[1], BRCTL_SET_PATH_COST, cost);
284 }
285
286 void br_set_port_prio(char **argv)
287
288   int prio;
289
290   prio = atolx_range(argv[2], 0, INT_MAX);
291   set_cost_prio(argv[0], argv[1], BRCTL_SET_PORT_PRIORITY, prio);
292
293 }
294
295 void brctl_main(void)
296 {
297   int i;
298   struct cmds {
299     char *cmd;
300     int nargs;
301     void (*f)(char **argv);
302   } cc[] = {{"show", 0, br_show},
303     {"addbr", 1, br_addbr}, {"delbr", 1, br_delbr},
304     {"addif", 2, br_addif}, {"delif", 2, br_delif},
305     {"setageing", 2, br_set_ageing_time},
306     {"setfd", 2, br_set_fwd_delay},
307     {"sethello", 2, br_set_hello_time},
308     {"setmaxage", 2, br_set_max_age},
309     {"setpathcost", 3, br_set_path_cost},
310     {"setportprio", 3, br_set_port_prio},
311     {"setbridgeprio", 2, br_set_bridge_prio},
312     {"stp", 2, br_set_stp},
313   };
314
315   TT.sockfd = xsocket(AF_INET, SOCK_STREAM, 0);
316   while (*toys.optargs) {
317     for (i = 0; i < ARRAY_LEN(cc); i++) {
318       struct cmds *t = cc + i;
319
320       if (strcmp(t->cmd, *toys.optargs)) continue;
321
322       toys.optargs++, toys.optc--;
323       if (toys.optc < t->nargs) {            
324         toys.exithelp++;
325         error_exit("check args");
326       }
327       t->f(toys.optargs);
328       toys.optargs += t->nargs;
329       toys.optc -= t->nargs;
330       break;
331     }
332
333     if (i == ARRAY_LEN(cc)) {
334       toys.exithelp++;
335       error_exit("invalid option '%s'", *toys.optargs);
336     }
337   }
338   xclose(TT.sockfd);
339 }