aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-04-13 13:58:06 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2019-04-13 13:58:06 +0200
commitdc1b2d43565dee709229dd76d856736bf543792d (patch)
tree1d52dc10eb19752f325586f77652af968f9b51b9
parentc5150e9ce7359db136ae9337b2f007c6f7ec3113 (diff)
downloadbusybox-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.c331
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
127struct __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 */
151static ALWAYS_INLINE void bb_strtotimeval(struct timeval *tv, 97static 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
192static 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
203static int read_file(const char *name) 141static 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 */
218static int show_bridge(const char *name, int need_hdr) 156static 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
211static 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
266int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 228int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
267int brctl_main(int argc UNUSED_PARAM, char **argv) 229int 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;