diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-04-13 13:58:06 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-04-13 13:58:06 +0200 |
commit | dc1b2d43565dee709229dd76d856736bf543792d (patch) | |
tree | 1d52dc10eb19752f325586f77652af968f9b51b9 | |
parent | c5150e9ce7359db136ae9337b2f007c6f7ec3113 (diff) | |
download | busybox-w32-dc1b2d43565dee709229dd76d856736bf543792d.tar.gz busybox-w32-dc1b2d43565dee709229dd76d856736bf543792d.tar.bz2 busybox-w32-dc1b2d43565dee709229dd76d856736bf543792d.zip |
brctl: convert remaining commands to work via /sys
function old new delta
write_ulong - 96 +96
show_bridge 310 338 +28
static.ops 3 - -3
arm_ioctl 20 - -20
packed_usage 33344 33315 -29
brctl_main 885 721 -164
------------------------------------------------------------------------------
(add/remove: 1/2 grow/shrink: 1/2 up/down: 124/-216) Total: -92 bytes
text data bss dec hex filename
982112 485 7296 989893 f1ac5 busybox_old
982157 485 7296 989938 f1af2 busybox_unstripped
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/brctl.c | 331 |
1 files changed, 147 insertions, 184 deletions
diff --git a/networking/brctl.c b/networking/brctl.c index 706ecfc07..804728e3c 100644 --- a/networking/brctl.c +++ b/networking/brctl.c | |||
@@ -44,27 +44,31 @@ | |||
44 | //kbuild:lib-$(CONFIG_BRCTL) += brctl.o | 44 | //kbuild:lib-$(CONFIG_BRCTL) += brctl.o |
45 | 45 | ||
46 | //usage:#define brctl_trivial_usage | 46 | //usage:#define brctl_trivial_usage |
47 | //usage: "COMMAND [BRIDGE [INTERFACE]]" | 47 | //usage: "COMMAND [BRIDGE [ARGS]]" |
48 | //usage:#define brctl_full_usage "\n\n" | 48 | //usage:#define brctl_full_usage "\n\n" |
49 | //usage: "Manage ethernet bridges\n" | 49 | //usage: "Manage ethernet bridges\n" |
50 | //usage: "\nCommands:" | 50 | //usage: "\nCommands:" |
51 | //usage: IF_FEATURE_BRCTL_SHOW( | 51 | //usage: IF_FEATURE_BRCTL_SHOW( |
52 | //usage: "\n show Show a list of bridges" | 52 | //usage: "\n show [BRIDGE]... Show bridges" |
53 | //usage: ) | 53 | //usage: ) |
54 | //usage: "\n addbr BRIDGE Create BRIDGE" | 54 | //usage: "\n addbr BRIDGE Create BRIDGE" |
55 | //usage: "\n delbr BRIDGE Delete BRIDGE" | 55 | //usage: "\n delbr BRIDGE Delete BRIDGE" |
56 | //usage: "\n addif BRIDGE IFACE Add IFACE to BRIDGE" | 56 | //usage: "\n addif BRIDGE IFACE Add IFACE to BRIDGE" |
57 | //usage: "\n delif BRIDGE IFACE Delete IFACE from BRIDGE" | 57 | //usage: "\n delif BRIDGE IFACE Delete IFACE from BRIDGE" |
58 | //usage: IF_FEATURE_BRCTL_FANCY( | 58 | //usage: IF_FEATURE_BRCTL_FANCY( |
59 | //usage: "\n setageing BRIDGE TIME Set ageing time" | 59 | //usage: "\n stp BRIDGE 1/yes/on|0/no/off STP on/off" |
60 | //usage: "\n setfd BRIDGE TIME Set bridge forward delay" | 60 | //usage: "\n setageing BRIDGE SECONDS Set ageing time" |
61 | //usage: "\n sethello BRIDGE TIME Set hello time" | 61 | //usage: "\n setfd BRIDGE SECONDS Set bridge forward delay" |
62 | //usage: "\n setmaxage BRIDGE TIME Set max message age" | 62 | //usage: "\n sethello BRIDGE SECONDS Set hello time" |
63 | //usage: "\n setpathcost BRIDGE COST Set path cost" | 63 | //usage: "\n setmaxage BRIDGE SECONDS Set max message age" |
64 | //usage: "\n setportprio BRIDGE PRIO Set port priority" | ||
65 | //usage: "\n setbridgeprio BRIDGE PRIO Set bridge priority" | 64 | //usage: "\n setbridgeprio BRIDGE PRIO Set bridge priority" |
66 | //usage: "\n stp BRIDGE [1/yes/on|0/no/off] STP on/off" | 65 | //usage: "\n setportprio BRIDGE IFACE PRIO Set port priority" |
66 | //usage: "\n setpathcost BRIDGE IFACE COST Set path cost" | ||
67 | //usage: ) | 67 | //usage: ) |
68 | // Not yet implemented: | ||
69 | // hairpin BRIDGE IFACE on|off Hairpin on/off | ||
70 | // showmacs BRIDGE List mac addrs | ||
71 | // showstp BRIDGE Show stp info | ||
68 | 72 | ||
69 | #include "libbb.h" | 73 | #include "libbb.h" |
70 | #include "common_bufsiz.h" | 74 | #include "common_bufsiz.h" |
@@ -84,69 +88,11 @@ | |||
84 | # define SIOCBRDELIF BRCTL_DEL_IF | 88 | # define SIOCBRDELIF BRCTL_DEL_IF |
85 | #endif | 89 | #endif |
86 | 90 | ||
87 | |||
88 | /* Maximum number of ports supported per bridge interface. */ | ||
89 | #ifndef MAX_PORTS | ||
90 | # define MAX_PORTS 32 | ||
91 | #endif | ||
92 | |||
93 | /* Use internal number parsing and not the "exact" conversion. */ | 91 | /* Use internal number parsing and not the "exact" conversion. */ |
94 | /* #define BRCTL_USE_INTERNAL 0 */ /* use exact conversion */ | 92 | /* #define BRCTL_USE_INTERNAL 0 */ /* use exact conversion */ |
95 | #define BRCTL_USE_INTERNAL 1 | 93 | #define BRCTL_USE_INTERNAL 1 |
96 | 94 | ||
97 | #if ENABLE_FEATURE_BRCTL_FANCY | 95 | #if ENABLE_FEATURE_BRCTL_FANCY |
98 | /* #include <linux/if_bridge.h> | ||
99 | * breaks on musl: we already included netinet/in.h in libbb.h, | ||
100 | * if we include <linux/if_bridge.h> here, we get this: | ||
101 | * In file included from /usr/include/linux/if_bridge.h:18, | ||
102 | * from networking/brctl.c:67: | ||
103 | * /usr/include/linux/in6.h:32: error: redefinition of 'struct in6_addr' | ||
104 | * /usr/include/linux/in6.h:49: error: redefinition of 'struct sockaddr_in6' | ||
105 | * /usr/include/linux/in6.h:59: error: redefinition of 'struct ipv6_mreq' | ||
106 | */ | ||
107 | /* From <linux/if_bridge.h> */ | ||
108 | #define BRCTL_GET_VERSION 0 | ||
109 | #define BRCTL_GET_BRIDGES 1 | ||
110 | #define BRCTL_ADD_BRIDGE 2 | ||
111 | #define BRCTL_DEL_BRIDGE 3 | ||
112 | #define BRCTL_ADD_IF 4 | ||
113 | #define BRCTL_DEL_IF 5 | ||
114 | #define BRCTL_GET_BRIDGE_INFO 6 | ||
115 | #define BRCTL_GET_PORT_LIST 7 | ||
116 | #define BRCTL_SET_BRIDGE_FORWARD_DELAY 8 | ||
117 | #define BRCTL_SET_BRIDGE_HELLO_TIME 9 | ||
118 | #define BRCTL_SET_BRIDGE_MAX_AGE 10 | ||
119 | #define BRCTL_SET_AGEING_TIME 11 | ||
120 | #define BRCTL_SET_GC_INTERVAL 12 | ||
121 | #define BRCTL_GET_PORT_INFO 13 | ||
122 | #define BRCTL_SET_BRIDGE_STP_STATE 14 | ||
123 | #define BRCTL_SET_BRIDGE_PRIORITY 15 | ||
124 | #define BRCTL_SET_PORT_PRIORITY 16 | ||
125 | #define BRCTL_SET_PATH_COST 17 | ||
126 | #define BRCTL_GET_FDB_ENTRIES 18 | ||
127 | struct __bridge_info { | ||
128 | uint64_t designated_root; | ||
129 | uint64_t bridge_id; | ||
130 | uint32_t root_path_cost; | ||
131 | uint32_t max_age; | ||
132 | uint32_t hello_time; | ||
133 | uint32_t forward_delay; | ||
134 | uint32_t bridge_max_age; | ||
135 | uint32_t bridge_hello_time; | ||
136 | uint32_t bridge_forward_delay; | ||
137 | uint8_t topology_change; | ||
138 | uint8_t topology_change_detected; | ||
139 | uint8_t root_port; | ||
140 | uint8_t stp_enabled; | ||
141 | uint32_t ageing_time; | ||
142 | uint32_t gc_interval; | ||
143 | uint32_t hello_timer_value; | ||
144 | uint32_t tcn_timer_value; | ||
145 | uint32_t topology_change_timer_value; | ||
146 | uint32_t gc_timer_value; | ||
147 | }; | ||
148 | /* end <linux/if_bridge.h> */ | ||
149 | |||
150 | /* FIXME: These 4 funcs are not really clean and could be improved */ | 96 | /* FIXME: These 4 funcs are not really clean and could be improved */ |
151 | static ALWAYS_INLINE void bb_strtotimeval(struct timeval *tv, | 97 | static ALWAYS_INLINE void bb_strtotimeval(struct timeval *tv, |
152 | const char *time_str) | 98 | const char *time_str) |
@@ -188,18 +134,10 @@ static unsigned long str_to_jiffies(const char *time_str) | |||
188 | bb_strtotimeval(&tv, time_str); | 134 | bb_strtotimeval(&tv, time_str); |
189 | return tv_to_jiffies(&tv); | 135 | return tv_to_jiffies(&tv); |
190 | } | 136 | } |
191 | |||
192 | static void arm_ioctl(unsigned long *args, | ||
193 | unsigned long arg0, unsigned long arg1, unsigned long arg2) | ||
194 | { | ||
195 | args[0] = arg0; | ||
196 | args[1] = arg1; | ||
197 | args[2] = arg2; | ||
198 | args[3] = 0; | ||
199 | } | ||
200 | #endif | 137 | #endif |
201 | 138 | ||
202 | #define filedata bb_common_bufsiz1 | 139 | #define filedata bb_common_bufsiz1 |
140 | |||
203 | static int read_file(const char *name) | 141 | static int read_file(const char *name) |
204 | { | 142 | { |
205 | int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1); | 143 | int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1); |
@@ -217,16 +155,21 @@ static int read_file(const char *name) | |||
217 | */ | 155 | */ |
218 | static int show_bridge(const char *name, int need_hdr) | 156 | static int show_bridge(const char *name, int need_hdr) |
219 | { | 157 | { |
220 | // Output: | 158 | /* Output: |
221 | //bridge name bridge id STP enabled interfaces | 159 | *bridge name bridge id STP enabled interfaces |
222 | //br0 8000.000000000000 no eth0 | 160 | *br0 8000.000000000000 no eth0 |
161 | */ | ||
223 | char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 32]; | 162 | char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 32]; |
224 | int tabs; | 163 | int tabs; |
225 | DIR *ifaces; | 164 | DIR *ifaces; |
226 | struct dirent *ent; | 165 | struct dirent *ent; |
227 | char *sfx; | 166 | char *sfx; |
228 | 167 | ||
229 | sfx = pathbuf + sprintf(pathbuf, "%s/bridge/", name); | 168 | #if IFNAMSIZ == 16 |
169 | sfx = pathbuf + sprintf(pathbuf, "%.16s/bridge/", name); | ||
170 | #else | ||
171 | sfx = pathbuf + sprintf(pathbuf, "%.*s/bridge/", (int)IFNAMSIZ, name); | ||
172 | #endif | ||
230 | strcpy(sfx, "bridge_id"); | 173 | strcpy(sfx, "bridge_id"); |
231 | if (read_file(pathbuf) < 0) | 174 | if (read_file(pathbuf) < 0) |
232 | return -1; /* this iface is not a bridge */ | 175 | return -1; /* this iface is not a bridge */ |
@@ -243,13 +186,15 @@ static int show_bridge(const char *name, int need_hdr) | |||
243 | else | 186 | else |
244 | if (LONE_CHAR(filedata, '1')) | 187 | if (LONE_CHAR(filedata, '1')) |
245 | strcpy(filedata, "yes"); | 188 | strcpy(filedata, "yes"); |
246 | printf(filedata); | 189 | fputs(filedata, stdout); |
247 | 190 | ||
248 | strcpy(sfx, "brif"); | 191 | strcpy(sfx - (sizeof("bridge/")-1), "brif"); |
249 | tabs = 0; | 192 | tabs = 0; |
250 | ifaces = opendir(pathbuf); | 193 | ifaces = opendir(pathbuf); |
251 | if (ifaces) { | 194 | if (ifaces) { |
252 | while ((ent = readdir(ifaces)) != NULL) { | 195 | while ((ent = readdir(ifaces)) != NULL) { |
196 | if (DOT_OR_DOTDOT(ent->d_name)) | ||
197 | continue; /* . or .. */ | ||
253 | if (tabs) | 198 | if (tabs) |
254 | printf("\t\t\t\t\t"); | 199 | printf("\t\t\t\t\t"); |
255 | else | 200 | else |
@@ -263,6 +208,23 @@ static int show_bridge(const char *name, int need_hdr) | |||
263 | return 0; | 208 | return 0; |
264 | } | 209 | } |
265 | 210 | ||
211 | static void write_ulong(const char *name, const char *leaf, unsigned long val) | ||
212 | { | ||
213 | char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 32]; | ||
214 | int fd, n; | ||
215 | |||
216 | #if IFNAMSIZ == 16 | ||
217 | sprintf(pathbuf, "%.16s/%s", name, leaf); | ||
218 | #else | ||
219 | sprintf(pathbuf, "%.*s/%s", (int)IFNAMSIZ, name, leaf); | ||
220 | #endif | ||
221 | fd = xopen(pathbuf, O_WRONLY); | ||
222 | n = sprintf(filedata, "%lu\n", val); | ||
223 | if (write(fd, filedata, n) < 0) | ||
224 | bb_simple_perror_msg_and_die(name); | ||
225 | close(fd); | ||
226 | } | ||
227 | |||
266 | int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 228 | int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
267 | int brctl_main(int argc UNUSED_PARAM, char **argv) | 229 | int brctl_main(int argc UNUSED_PARAM, char **argv) |
268 | { | 230 | { |
@@ -271,24 +233,20 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
271 | IF_FEATURE_BRCTL_FANCY( | 233 | IF_FEATURE_BRCTL_FANCY( |
272 | "stp\0" | 234 | "stp\0" |
273 | "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" | 235 | "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" |
274 | "setpathcost\0" "setportprio\0" "setbridgeprio\0" | 236 | "setpathcost\0" "setportprio\0" |
237 | "setbridgeprio\0" | ||
275 | ) | 238 | ) |
276 | IF_FEATURE_BRCTL_SHOW("show\0"); | 239 | IF_FEATURE_BRCTL_SHOW("show\0"); |
277 | |||
278 | enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif | 240 | enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif |
279 | IF_FEATURE_BRCTL_FANCY(, | 241 | IF_FEATURE_BRCTL_FANCY(, |
280 | ARG_stp, | 242 | ARG_stp, |
281 | ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, | 243 | ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, |
282 | ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio | 244 | ARG_setpathcost, ARG_setportprio, |
245 | ARG_setbridgeprio | ||
283 | ) | 246 | ) |
284 | IF_FEATURE_BRCTL_SHOW(, ARG_show) | 247 | IF_FEATURE_BRCTL_SHOW(, ARG_show) |
285 | }; | 248 | }; |
286 | 249 | ||
287 | int fd; | ||
288 | smallint key; | ||
289 | struct ifreq ifr; | ||
290 | char *br, *brif; | ||
291 | |||
292 | argv++; | 250 | argv++; |
293 | if (!*argv) { | 251 | if (!*argv) { |
294 | /* bare "brctl" shows --help */ | 252 | /* bare "brctl" shows --help */ |
@@ -297,12 +255,10 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
297 | 255 | ||
298 | xchdir("/sys/class/net"); | 256 | xchdir("/sys/class/net"); |
299 | 257 | ||
300 | while (*argv) { | 258 | // while (*argv) |
301 | #if ENABLE_FEATURE_BRCTL_FANCY | 259 | { |
302 | int ifidx[MAX_PORTS]; | 260 | smallint key; |
303 | unsigned long args[4]; | 261 | char *br; |
304 | ifr.ifr_data = (char *) &args; | ||
305 | #endif | ||
306 | 262 | ||
307 | key = index_in_strings(keywords, *argv); | 263 | key = index_in_strings(keywords, *argv); |
308 | if (key == -1) /* no match found in keywords array, bail out. */ | 264 | if (key == -1) /* no match found in keywords array, bail out. */ |
@@ -310,28 +266,28 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
310 | argv++; | 266 | argv++; |
311 | 267 | ||
312 | #if ENABLE_FEATURE_BRCTL_SHOW | 268 | #if ENABLE_FEATURE_BRCTL_SHOW |
313 | if (key == ARG_show) { /* show */ | 269 | if (key == ARG_show) { /* show [BR]... */ |
314 | DIR *net; | 270 | DIR *net; |
315 | struct dirent *ent; | 271 | struct dirent *ent; |
316 | int need_hdr = 1; | 272 | int need_hdr = 1; |
317 | int exitcode = EXIT_SUCCESS; | 273 | int exitcode = EXIT_SUCCESS; |
318 | 274 | ||
319 | if (*argv) { | 275 | if (*argv) { |
320 | /* "brctl show BR1 BR2 BR3" */ | 276 | /* "show BR1 BR2 BR3" */ |
321 | do { | 277 | do { |
322 | if (show_bridge(*argv, need_hdr) >= 0) { | 278 | if (show_bridge(*argv, need_hdr) >= 0) { |
323 | need_hdr = 0; | 279 | need_hdr = 0; |
324 | } else { | 280 | } else { |
325 | bb_error_msg("bridge %s does not exist", *argv); | 281 | bb_error_msg("bridge %s does not exist", *argv); |
326 | //TODO: if device exists, but is not a BR, brctl from bridge-utils 1.6 says this instead: | 282 | //TODO: if device exists, but is not a BR, brctl from bridge-utils 1.6 |
327 | // "device eth0 is not a bridge" | 283 | //says this instead: "device eth0 is not a bridge" |
328 | exitcode = EXIT_FAILURE; | 284 | exitcode = EXIT_FAILURE; |
329 | } | 285 | } |
330 | } while (*++argv != NULL); | 286 | } while (*++argv != NULL); |
331 | return exitcode; | 287 | return exitcode; |
332 | } | 288 | } |
333 | 289 | ||
334 | /* "brctl show" (if no ifaces, shows nothing, not even header) */ | 290 | /* "show" (if no ifaces, shows nothing, not even header) */ |
335 | net = xopendir("."); | 291 | net = xopendir("."); |
336 | while ((ent = readdir(net)) != NULL) { | 292 | while ((ent = readdir(net)) != NULL) { |
337 | if (DOT_OR_DOTDOT(ent->d_name)) | 293 | if (DOT_OR_DOTDOT(ent->d_name)) |
@@ -339,7 +295,8 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
339 | if (show_bridge(ent->d_name, need_hdr) >= 0) | 295 | if (show_bridge(ent->d_name, need_hdr) >= 0) |
340 | need_hdr = 0; | 296 | need_hdr = 0; |
341 | } | 297 | } |
342 | closedir(net); | 298 | if (ENABLE_FEATURE_CLEAN_UP) |
299 | closedir(net); | ||
343 | return exitcode; | 300 | return exitcode; |
344 | } | 301 | } |
345 | #endif | 302 | #endif |
@@ -347,33 +304,31 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
347 | if (!*argv) /* all but 'show' need at least one argument */ | 304 | if (!*argv) /* all but 'show' need at least one argument */ |
348 | bb_show_usage(); | 305 | bb_show_usage(); |
349 | 306 | ||
350 | fd = xsocket(AF_INET, SOCK_STREAM, 0); | ||
351 | br = *argv++; | 307 | br = *argv++; |
352 | 308 | ||
353 | //brctl from bridge-utils 1.6 also still uses ioctl | 309 | if (key == ARG_addbr || key == ARG_delbr) { |
354 | //for SIOCBRADDBR / SIOCBRDELBR, not /sys accesses | 310 | /* addbr or delbr */ |
355 | if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */ | 311 | /* brctl from bridge-utils 1.6 still uses ioctl |
312 | * for SIOCBRADDBR / SIOCBRDELBR, not /sys accesses | ||
313 | */ | ||
314 | int fd = xsocket(AF_INET, SOCK_STREAM, 0); | ||
356 | ioctl_or_perror_and_die(fd, | 315 | ioctl_or_perror_and_die(fd, |
357 | key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, | 316 | key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, |
358 | br, "bridge %s", br); | 317 | br, "bridge %s", br |
359 | goto done; | 318 | ); |
319 | //close(fd); | ||
320 | //goto done; | ||
321 | /* bridge-utils 1.6 simply ignores trailing args: | ||
322 | * "brctl addbr BR1 ARGS" ignores ARGS | ||
323 | */ | ||
324 | if (ENABLE_FEATURE_CLEAN_UP) | ||
325 | close(fd); | ||
326 | return EXIT_SUCCESS; | ||
360 | } | 327 | } |
361 | 328 | ||
362 | if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ | 329 | if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ |
363 | bb_show_usage(); | 330 | bb_show_usage(); |
364 | 331 | ||
365 | strncpy_IFNAMSIZ(ifr.ifr_name, br); | ||
366 | if (key == ARG_addif || key == ARG_delif) { /* addif or delif */ | ||
367 | brif = *argv; | ||
368 | ifr.ifr_ifindex = if_nametoindex(brif); | ||
369 | if (!ifr.ifr_ifindex) { | ||
370 | bb_perror_msg_and_die("iface %s", brif); | ||
371 | } | ||
372 | ioctl_or_perror_and_die(fd, | ||
373 | key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, | ||
374 | &ifr, "bridge %s", br); | ||
375 | goto done_next_argv; | ||
376 | } | ||
377 | #if ENABLE_FEATURE_BRCTL_FANCY | 332 | #if ENABLE_FEATURE_BRCTL_FANCY |
378 | if (key == ARG_stp) { /* stp */ | 333 | if (key == ARG_stp) { /* stp */ |
379 | static const char no_yes[] ALIGN1 = | 334 | static const char no_yes[] ALIGN1 = |
@@ -382,78 +337,86 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
382 | int onoff = index_in_strings(no_yes, *argv); | 337 | int onoff = index_in_strings(no_yes, *argv); |
383 | if (onoff < 0) | 338 | if (onoff < 0) |
384 | bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); | 339 | bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); |
385 | //TODO: replace with: | ||
386 | //write "0\n" or "1\n" to /sys/class/net/BR/bridge/stp_state | ||
387 | onoff = (unsigned)onoff / 4; | 340 | onoff = (unsigned)onoff / 4; |
388 | arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0); | 341 | write_ulong(br, "bridge/stp_state", onoff); |
389 | goto fire; | 342 | //goto done_next_argv; |
343 | return EXIT_SUCCESS; | ||
390 | } | 344 | } |
345 | |||
391 | if ((unsigned)(key - ARG_setageing) < 4) { /* time related ops */ | 346 | if ((unsigned)(key - ARG_setageing) < 4) { /* time related ops */ |
392 | static const uint8_t ops[] ALIGN1 = { | 347 | /* setageing BR N: "N*100\n" to /sys/class/net/BR/bridge/ageing_time |
393 | BRCTL_SET_AGEING_TIME, /* ARG_setageing */ | 348 | * setfd BR N: "N*100\n" to /sys/class/net/BR/bridge/forward_delay |
394 | BRCTL_SET_BRIDGE_FORWARD_DELAY, /* ARG_setfd */ | 349 | * sethello BR N: "N*100\n" to /sys/class/net/BR/bridge/hello_time |
395 | BRCTL_SET_BRIDGE_HELLO_TIME, /* ARG_sethello */ | 350 | * setmaxage BR N: "N*100\n" to /sys/class/net/BR/bridge/max_age |
396 | BRCTL_SET_BRIDGE_MAX_AGE /* ARG_setmaxage */ | 351 | */ |
397 | }; | 352 | write_ulong(br, |
398 | //TODO: replace with: | 353 | nth_string( |
399 | //setageing BR N: write "N*100\n" to /sys/class/net/BR/bridge/ageing_time | 354 | "bridge/ageing_time" "\0" /* ARG_setageing */ |
400 | //setfd BR N: write "N*100\n" to /sys/class/net/BR/bridge/forward_delay | 355 | "bridge/forward_delay""\0" /* ARG_setfd */ |
401 | //sethello BR N: write "N*100\n" to /sys/class/net/BR/bridge/hello_time | 356 | "bridge/hello_time" "\0" /* ARG_sethello */ |
402 | //setmaxage BR N: write "N*100\n" to /sys/class/net/BR/bridge/max_age | 357 | "bridge/max_age", /* ARG_setmaxage */ |
403 | arm_ioctl(args, ops[key - ARG_setageing], str_to_jiffies(*argv), 0); | 358 | key - ARG_setageing |
404 | goto fire; | 359 | ), |
360 | str_to_jiffies(*argv) | ||
361 | ); | ||
362 | //goto done_next_argv; | ||
363 | return EXIT_SUCCESS; | ||
364 | } | ||
365 | |||
366 | if (key == ARG_setbridgeprio) { | ||
367 | write_ulong(br, "bridge/priority", xatoi_positive(*argv)); | ||
368 | //goto done_next_argv; | ||
369 | return EXIT_SUCCESS; | ||
405 | } | 370 | } |
371 | |||
406 | if (key == ARG_setpathcost | 372 | if (key == ARG_setpathcost |
407 | || key == ARG_setportprio | 373 | || key == ARG_setportprio |
408 | || key == ARG_setbridgeprio | ||
409 | ) { | 374 | ) { |
410 | static const uint8_t ops[] ALIGN1 = { | 375 | if (!argv[1]) |
411 | BRCTL_SET_PATH_COST, /* ARG_setpathcost */ | 376 | bb_show_usage(); |
412 | BRCTL_SET_PORT_PRIORITY, /* ARG_setportprio */ | 377 | /* BR is not used (and ignored!) for these commands: |
413 | BRCTL_SET_BRIDGE_PRIORITY /* ARG_setbridgeprio */ | 378 | * "setpathcost BR PORT N" writes "N\n" to |
414 | }; | 379 | * /sys/class/net/PORT/brport/path_cost |
415 | int port = -1; | 380 | * "setportprio BR PORT N" writes "N\n" to |
416 | unsigned arg1, arg2; | 381 | * /sys/class/net/PORT/brport/priority |
417 | 382 | */ | |
418 | //TODO: replace with: | 383 | write_ulong(argv[0], |
419 | //setbridgeprio BR N: write "N\n" to /sys/class/net/BR/bridge/priority | 384 | nth_string( |
420 | //setpathcost BR PORT N: ?? | 385 | "brport/path_cost" "\0" /* ARG_setpathcost */ |
421 | //setportprio BR PORT N: ?? | 386 | "brport/priority", /* ARG_setportprio */ |
422 | 387 | key - ARG_setpathcost | |
423 | if (key != ARG_setbridgeprio) { | 388 | ), |
424 | /* get portnum */ | 389 | xatoi_positive(argv[1]) |
425 | unsigned i; | 390 | ); |
426 | 391 | //argv++; | |
427 | port = if_nametoindex(*argv++); | 392 | //goto done_next_argv; |
428 | if (!port) | 393 | return EXIT_SUCCESS; |
429 | bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, "port"); | ||
430 | memset(ifidx, 0, sizeof ifidx); | ||
431 | arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx, | ||
432 | MAX_PORTS); | ||
433 | xioctl(fd, SIOCDEVPRIVATE, &ifr); | ||
434 | for (i = 0; i < MAX_PORTS; i++) { | ||
435 | if (ifidx[i] == port) { | ||
436 | port = i; | ||
437 | break; | ||
438 | } | ||
439 | } | ||
440 | } | ||
441 | arg1 = port; | ||
442 | arg2 = xatoi_positive(*argv); | ||
443 | if (key == ARG_setbridgeprio) { | ||
444 | arg1 = arg2; | ||
445 | arg2 = 0; | ||
446 | } | ||
447 | arm_ioctl(args, ops[key - ARG_setpathcost], arg1, arg2); | ||
448 | } | 394 | } |
449 | fire: | ||
450 | /* Execute the previously set command */ | ||
451 | xioctl(fd, SIOCDEVPRIVATE, &ifr); | ||
452 | #endif | 395 | #endif |
453 | done_next_argv: | 396 | /* always true: if (key == ARG_addif || key == ARG_delif) */ { |
454 | argv++; | 397 | /* addif or delif */ |
455 | done: | 398 | struct ifreq ifr; |
456 | close(fd); | 399 | int fd = xsocket(AF_INET, SOCK_STREAM, 0); |
400 | |||
401 | strncpy_IFNAMSIZ(ifr.ifr_name, br); | ||
402 | ifr.ifr_ifindex = if_nametoindex(*argv); | ||
403 | if (ifr.ifr_ifindex == 0) { | ||
404 | bb_perror_msg_and_die("iface %s", *argv); | ||
405 | } | ||
406 | ioctl_or_perror_and_die(fd, | ||
407 | key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, | ||
408 | &ifr, "bridge %s", br | ||
409 | ); | ||
410 | //close(fd); | ||
411 | //goto done_next_argv; | ||
412 | if (ENABLE_FEATURE_CLEAN_UP) | ||
413 | close(fd); | ||
414 | return EXIT_SUCCESS; | ||
415 | } | ||
416 | |||
417 | // done_next_argv: | ||
418 | // argv++; | ||
419 | // done: | ||
457 | } | 420 | } |
458 | 421 | ||
459 | return EXIT_SUCCESS; | 422 | return EXIT_SUCCESS; |