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; |
