Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/networking/brctl.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 7209 byte(s)
-updated to busybox-1.13.4
1 niro 816 /* vi: set sw=4 ts=4: */
2     /*
3     * Small implementation of brctl for busybox.
4     *
5     * Copyright (C) 2008 by Bernhard Reutner-Fischer
6     *
7     * Some helper functions from bridge-utils are
8     * Copyright (C) 2000 Lennert Buytenhek
9     *
10     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11     */
12     /* This applet currently uses only the ioctl interface and no sysfs at all.
13     * At the time of this writing this was considered a feature.
14     */
15     #include "libbb.h"
16     #include <linux/sockios.h>
17     #include <net/if.h>
18    
19     /* Maximum number of ports supported per bridge interface. */
20     #ifndef MAX_PORTS
21     #define MAX_PORTS 32
22     #endif
23    
24     /* Use internal number parsing and not the "exact" conversion. */
25     /* #define BRCTL_USE_INTERNAL 0 */ /* use exact conversion */
26     #define BRCTL_USE_INTERNAL 1
27    
28     #if ENABLE_FEATURE_BRCTL_FANCY
29     #include <linux/if_bridge.h>
30    
31     /* FIXME: These 4 funcs are not really clean and could be improved */
32     static ALWAYS_INLINE void strtotimeval(struct timeval *tv,
33     const char *time_str)
34     {
35     double secs;
36     #if BRCTL_USE_INTERNAL
37     secs = /*bb_*/strtod(time_str, NULL);
38     if (!secs)
39     #else
40     if (sscanf(time_str, "%lf", &secs) != 1)
41     #endif
42     bb_error_msg_and_die (bb_msg_invalid_arg, time_str, "timespec");
43     tv->tv_sec = secs;
44     tv->tv_usec = 1000000 * (secs - tv->tv_sec);
45     }
46    
47     static ALWAYS_INLINE unsigned long __tv_to_jiffies(const struct timeval *tv)
48     {
49     unsigned long long jif;
50    
51     jif = 1000000ULL * tv->tv_sec + tv->tv_usec;
52    
53     return jif/10000;
54     }
55     # if 0
56     static void __jiffies_to_tv(struct timeval *tv, unsigned long jiffies)
57     {
58     unsigned long long tvusec;
59    
60     tvusec = 10000ULL*jiffies;
61     tv->tv_sec = tvusec/1000000;
62     tv->tv_usec = tvusec - 1000000 * tv->tv_sec;
63     }
64     # endif
65     static unsigned long str_to_jiffies(const char *time_str)
66     {
67     struct timeval tv;
68     strtotimeval(&tv, time_str);
69     return __tv_to_jiffies(&tv);
70     }
71    
72     static void arm_ioctl(unsigned long *args,
73     unsigned long arg0, unsigned long arg1, unsigned long arg2)
74     {
75     args[0] = arg0;
76     args[1] = arg1;
77     args[2] = arg2;
78     args[3] = 0;
79     }
80     #endif
81    
82    
83     int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
84     int brctl_main(int argc UNUSED_PARAM, char **argv)
85     {
86     static const char keywords[] ALIGN1 =
87     "addbr\0" "delbr\0" "addif\0" "delif\0"
88     USE_FEATURE_BRCTL_FANCY(
89     "stp\0"
90     "setageing\0" "setfd\0" "sethello\0" "setmaxage\0"
91     "setpathcost\0" "setportprio\0" "setbridgeprio\0"
92     )
93     USE_FEATURE_BRCTL_SHOW("showmacs\0" "show\0");
94    
95     enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
96     USE_FEATURE_BRCTL_FANCY(,
97     ARG_stp,
98     ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
99     ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio
100     )
101     USE_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show)
102     };
103    
104     int fd;
105     smallint key;
106     struct ifreq ifr;
107     char *br, *brif;
108    
109     argv++;
110     while (*argv) {
111     #if ENABLE_FEATURE_BRCTL_FANCY
112     int ifidx[MAX_PORTS];
113     unsigned long args[4];
114     ifr.ifr_data = (char *) &args;
115     #endif
116    
117     key = index_in_strings(keywords, *argv);
118     if (key == -1) /* no match found in keywords array, bail out. */
119     bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
120     argv++;
121     fd = xsocket(AF_INET, SOCK_STREAM, 0);
122    
123     #if ENABLE_FEATURE_BRCTL_SHOW
124     if (key == ARG_show) { /* show */
125     char brname[IFNAMSIZ];
126     int bridx[MAX_PORTS];
127     int i, num;
128     arm_ioctl(args, BRCTL_GET_BRIDGES,
129     (unsigned long) bridx, MAX_PORTS);
130     num = xioctl(fd, SIOCGIFBR, args);
131     printf("bridge name\tbridge id\t\tSTP enabled\tinterfaces\n");
132     for (i = 0; i < num; i++) {
133     char ifname[IFNAMSIZ];
134     int j, tabs;
135     struct __bridge_info bi;
136     unsigned char *x;
137    
138     if (!if_indextoname(bridx[i], brname))
139     bb_perror_msg_and_die("can't get bridge name for index %d", i);
140     strncpy(ifr.ifr_name, brname, IFNAMSIZ);
141    
142     arm_ioctl(args, BRCTL_GET_BRIDGE_INFO,
143     (unsigned long) &bi, 0);
144     xioctl(fd, SIOCDEVPRIVATE, &ifr);
145     printf("%s\t\t", brname);
146    
147     /* print bridge id */
148     x = (unsigned char *) &bi.bridge_id;
149     for (j = 0; j < 8; j++) {
150     printf("%.2x", x[j]);
151     if (j == 1)
152     bb_putchar('.');
153     }
154     printf(bi.stp_enabled ? "\tyes" : "\tno");
155    
156     /* print interface list */
157     arm_ioctl(args, BRCTL_GET_PORT_LIST,
158     (unsigned long) ifidx, MAX_PORTS);
159     xioctl(fd, SIOCDEVPRIVATE, &ifr);
160     tabs = 0;
161     for (j = 0; j < MAX_PORTS; j++) {
162     if (!ifidx[j])
163     continue;
164     if (!if_indextoname(ifidx[j], ifname))
165     bb_perror_msg_and_die("can't get interface name for index %d", j);
166     if (tabs)
167     printf("\t\t\t\t\t");
168     else
169     tabs = 1;
170     printf("\t\t%s\n", ifname);
171     }
172     if (!tabs) /* bridge has no interfaces */
173     bb_putchar('\n');
174     }
175     goto done;
176     }
177     #endif
178    
179     if (!*argv) /* all but 'show' need at least one argument */
180     bb_show_usage();
181    
182     br = *argv++;
183    
184     if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */
185     ioctl_or_perror_and_die(fd,
186     key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR,
187     br, "bridge %s", br);
188     goto done;
189     }
190    
191     if (!*argv) /* all but 'addif/delif' need at least two arguments */
192     bb_show_usage();
193    
194     strncpy(ifr.ifr_name, br, IFNAMSIZ);
195     if (key == ARG_addif || key == ARG_delif) { /* addif or delif */
196     brif = *argv;
197     ifr.ifr_ifindex = if_nametoindex(brif);
198     if (!ifr.ifr_ifindex) {
199     bb_perror_msg_and_die("iface %s", brif);
200     }
201     ioctl_or_perror_and_die(fd,
202     key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF,
203     &ifr, "bridge %s", br);
204     goto done_next_argv;
205     }
206     #if ENABLE_FEATURE_BRCTL_FANCY
207     if (key == ARG_stp) { /* stp */
208     /* FIXME: parsing yes/y/on/1 versus no/n/off/0 is too involved */
209     arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE,
210     (unsigned)(**argv - '0'), 0);
211     goto fire;
212     }
213     if ((unsigned)(key - ARG_setageing) < 4) { /* time related ops */
214     static const uint8_t ops[] ALIGN1 = {
215     BRCTL_SET_AGEING_TIME, /* ARG_setageing */
216     BRCTL_SET_BRIDGE_FORWARD_DELAY, /* ARG_setfd */
217     BRCTL_SET_BRIDGE_HELLO_TIME, /* ARG_sethello */
218     BRCTL_SET_BRIDGE_MAX_AGE /* ARG_setmaxage */
219     };
220     arm_ioctl(args, ops[key - ARG_setageing], str_to_jiffies(*argv), 0);
221     goto fire;
222     }
223     if (key == ARG_setpathcost
224     || key == ARG_setportprio
225     || key == ARG_setbridgeprio
226     ) {
227     static const uint8_t ops[] ALIGN1 = {
228     BRCTL_SET_PATH_COST, /* ARG_setpathcost */
229     BRCTL_SET_PORT_PRIORITY, /* ARG_setportprio */
230     BRCTL_SET_BRIDGE_PRIORITY /* ARG_setbridgeprio */
231     };
232     int port = -1;
233     unsigned arg1, arg2;
234    
235     if (key != ARG_setbridgeprio) {
236     /* get portnum */
237     unsigned i;
238    
239     port = if_nametoindex(*argv++);
240     if (!port)
241     bb_error_msg_and_die(bb_msg_invalid_arg, *argv, "port");
242     memset(ifidx, 0, sizeof ifidx);
243     arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx,
244     MAX_PORTS);
245     xioctl(fd, SIOCDEVPRIVATE, &ifr);
246     for (i = 0; i < MAX_PORTS; i++) {
247     if (ifidx[i] == port) {
248     port = i;
249     break;
250     }
251     }
252     }
253     arg1 = port;
254     arg2 = xatoi_u(*argv);
255     if (key == ARG_setbridgeprio) {
256     arg1 = arg2;
257     arg2 = 0;
258     }
259     arm_ioctl(args, ops[key - ARG_setpathcost], arg1, arg2);
260     }
261     fire:
262     /* Execute the previously set command */
263     xioctl(fd, SIOCDEVPRIVATE, &ifr);
264     #endif
265     done_next_argv:
266     argv++;
267     done:
268     close(fd);
269     }
270    
271     return EXIT_SUCCESS;
272     }