diff options
author | Bernhard Reutner-Fischer | 2008-01-14 16:10:11 +0000 |
---|---|---|
committer | Bernhard Reutner-Fischer | 2008-01-14 16:10:11 +0000 |
commit | 2b11fb483e663149d79992021cc4e495e0df8677 (patch) | |
tree | f5567e7905409192b150afa7dde907264815b7f8 /networking/brctl.c | |
parent | c2f0de5eef4feeca5d993ff3553b0e196862282f (diff) | |
download | busybox-2b11fb483e663149d79992021cc4e495e0df8677.zip busybox-2b11fb483e663149d79992021cc4e495e0df8677.tar.gz |
- implement brctl setpathcost, setportprio, setbridgeprio, stp
text data bss dec hex filename
907 20 0 927 39f networking/brctl.o
Diffstat (limited to 'networking/brctl.c')
-rw-r--r-- | networking/brctl.c | 113 |
1 files changed, 92 insertions, 21 deletions
diff --git a/networking/brctl.c b/networking/brctl.c index 7c9d90f..bbd14c4 100644 --- a/networking/brctl.c +++ b/networking/brctl.c @@ -4,6 +4,9 @@ * * Copyright (C) 2008 by Bernhard Fischer * + * Some helper functions from bridge-utils are + * Copyright (C) 2000 Lennert Buytenhek + * * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ /* This applet currently uses only the ioctl interface and no sysfs at all. @@ -13,19 +16,21 @@ #include <linux/sockios.h> #include <net/if.h> +/* Maximum number of ports supported per bridge interface. */ +#ifndef MAX_PORTS +#define MAX_PORTS 32 +#endif + +/* Use internal number parsing and not the "exact" conversion. */ +/* #define BRCTL_USE_INTERNAL 0 */ /* use exact conversion */ +#define BRCTL_USE_INTERNAL 1 + #ifdef ENABLE_FEATURE_BRCTL_SHOW #error Remove these #endif #define ENABLE_FEATURE_BRCTL_SHOW 0 #define USE_FEATURE_BRCTL_SHOW(...) -#if 0 -#define ENABLE_FEATURE_BRCTL_FANCY 0 -#if ENABLE_FEATURE_BRCTL_FANCY -#define USE_FEATURE_BRCTL_FANCY(...) __VA_ARGS__ -#else -#define USE_FEATURE_BRCTL_FANCY(...) -#endif -#endif + #if ENABLE_FEATURE_BRCTL_FANCY #include <linux/if_bridge.h> /* FIXME: These 4 funcs are not really clean and could be improved */ @@ -33,7 +38,11 @@ static inline ALWAYS_INLINE void strtotimeval(struct timeval *tv, const char *time_str) { double secs; +#if BRCTL_USE_INTERNAL + if (!(secs = /*bb_*/strtod(time_str, NULL))) +#else if (sscanf(time_str, "%lf", &secs) != 1) +#endif bb_error_msg_and_die (bb_msg_invalid_arg, time_str, "timespec"); tv->tv_sec = secs; tv->tv_usec = 1000000 * (secs - tv->tv_sec); @@ -47,7 +56,7 @@ static inline ALWAYS_INLINE unsigned long __tv_to_jiffies(const struct timeval * return jif/10000; } -# ifdef UNUSED && 00 +# if 00 static void __jiffies_to_tv(struct timeval *tv, unsigned long jiffies) { unsigned long long tvusec; @@ -63,6 +72,15 @@ static unsigned long str_to_jiffies(const char *time_str) strtotimeval(&tv, time_str); return __tv_to_jiffies(&tv); } + +static void arm_ioctl(unsigned long *args, + unsigned long arg0, unsigned long arg1, unsigned long arg2) +{ + args[0] = arg0; + args[1] = arg1; + args[2] = arg2; + args[3] = 0; +} #endif @@ -73,22 +91,27 @@ int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv) static const char keywords[] ALIGN1 = "addbr\0" "delbr\0" "addif\0" "delif\0" USE_FEATURE_BRCTL_FANCY( + "stp\0" "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" "setpathcost\0" "setportprio\0" "setbridgeprio\0" - "stp\0" ) USE_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif USE_FEATURE_BRCTL_FANCY(, + ARG_stp, ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, - ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio, - ARG_stp + ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio ) USE_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) }; smallint key; struct ifreq ifr; static char info[] = "bridge %s\0 iface %s"; - char *br; + char *br, *brif; +#if ENABLE_FEATURE_BRCTL_FANCY + unsigned long args[4] = {0, 0, 0, 0}; + int port; + int tmp; +#endif argv++; while (*argv) { @@ -114,8 +137,6 @@ int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv) bb_show_usage(); safe_strncpy(ifr.ifr_name, br, IFNAMSIZ); if (key == ARG_addif || key == ARG_delif) { /* addif or delif */ - char *brif; - brif = *(argv++); if (!(ifr.ifr_ifindex = if_nametoindex(brif))) { bb_perror_msg_and_die(info+11, brif); @@ -123,24 +144,74 @@ int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv) ioctl_or_perror_and_die(fd, key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, &ifr, info, br); + goto done; } #if ENABLE_FEATURE_BRCTL_FANCY - if (key - ARG_delif < 5) { /* time related ops */ + ifr.ifr_data = (char *) &args; + if (key == ARG_stp) { /* stp */ + /* FIXME: parsing yes/y/on/1 versus no/n/off/0 is too involved */ + arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, + (unsigned)(**argv - '0'), 0); + goto fire; + } + if ((unsigned)(key - ARG_stp) < 5) { /* time related ops */ unsigned long op = (key == ARG_setageing) ? BRCTL_SET_AGEING_TIME : (key == ARG_setfd) ? BRCTL_SET_BRIDGE_FORWARD_DELAY: (key == ARG_sethello) ? BRCTL_SET_BRIDGE_HELLO_TIME: (key == ARG_setmaxage) ? BRCTL_SET_BRIDGE_MAX_AGE : - -1/*will never be used */; - unsigned long jiff = str_to_jiffies (*(argv++)); - unsigned long args[4] = {op, jiff, 0, 0}; - ifr.ifr_data = (char *) &args; + -1/* will never be used */; + arm_ioctl(args, op, str_to_jiffies (*argv), 0); + goto fire; + } + port = -1; + if (key == ARG_setpathcost || key == ARG_setportprio) {/* get portnum */ + int ifidx[MAX_PORTS]; + unsigned i; + + if (!(port = if_nametoindex(*argv))) + bb_error_msg_and_die(bb_msg_invalid_arg, *argv, "port"); + argv++; + memset(ifidx, 0, sizeof ifidx); + arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx, + MAX_PORTS); xioctl(fd, SIOCDEVPRIVATE, &ifr); + for (i = 0; i < MAX_PORTS; i++) + if (ifidx[i] == port) { + port = i; + break; + } } + if (key == ARG_setpathcost + || key == ARG_setportprio || key == ARG_setbridgeprio) { + unsigned long op = (key == ARG_setpathcost) ? BRCTL_SET_PATH_COST : + (key == ARG_setportprio) ? BRCTL_SET_PORT_PRIORITY : + (key == ARG_setbridgeprio) ? BRCTL_SET_BRIDGE_PRIORITY : + -1/* will never be used */; + unsigned long arg1 = port; + unsigned long arg2; +# if BRCTL_USE_INTERNAL + tmp = xatoi(*argv); +# else + if (sscanf(*argv, "%i", &tmp) != 1) + bb_error_msg_and_die(bb_msg_invalid_arg, *argv, + key == ARG_setpathcost ? "cost" : "prio"); +# endif + if (key == ARG_setbridgeprio) { + arg1 = tmp; + arg2 = 0; + } else + arg2 = tmp; + arm_ioctl(args, op, arg1, arg2); + } + fire: + /* Execute the previously set command. */ + xioctl(fd, SIOCDEVPRIVATE, &ifr); + argv++; #endif done: if (ENABLE_FEATURE_CLEAN_UP) close(fd); } - out: +USE_FEATURE_BRCTL_SHOW(out:) return EXIT_SUCCESS; } |