Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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