- shrink a bit and implement time related fancy features. Improve help texts. text data bss dec hex filename 253 20 0 273 111 networking/brctl.o.bare 613 20 0 633 279 networking/brctl.o.fancy-time
No binary (build failed)
—
(log yok)
| @@ -127,8 +127,13 @@ | |
| " addbr <bridge> Create <bridge>\n" \ | |
| " delbr <bridge> Delete <bridge>\n" \ | |
| " addif <bridge> <iface> Add <iface> to <bridge>\n" \ | |
| - | " delif <bridge> <iface> Delete <iface> from <bridge>" |
| - | |
| + | " delif <bridge> <iface> Delete <iface> from <bridge>" \ |
| + | USE_FEATURE_BRCTL_FANCY("\n" \ |
| + | " setageing <bridge <time> set ageing time\n" \ |
| + | " setfd <bridge <time> set bridge forward delay\n" \ |
| + | " sethello <bridge <time> set hello time\n" \ |
| + | " setmaxage <bridge <time> set max message age\n" \ |
| + | ) |
| #define bunzip2_trivial_usage \ | |
| "[OPTION]... [FILE]" | |
| #define bunzip2_full_usage \ | |
| @@ -52,6 +52,25 @@ config BRCTL | |
| default n | |
| help | |
| Manage ethernet bridges. | |
| + | Supports addbr/delbr and addif/delif. |
| + | |
| + | #config FEATURE_BRCTL_SHOW |
| + | # bool "support show, showmac and showstp" |
| + | # default n |
| + | # depends on BRCTL |
| + | # help |
| + | # Add support for option which print the current config: |
| + | # showmacs, showstp, show |
| + | |
| + | config FEATURE_BRCTL_FANCY |
| + | bool "fancy options" |
| + | default n |
| + | depends on BRCTL |
| + | help |
| + | Add support for extended option like: |
| + | setageing, setfd, sethello, setmaxage, |
| + | setpathcost, setportprio, setbridgeprio, |
| + | stp |
| config DNSD | |
| bool "dnsd" | |
| @@ -6,6 +6,9 @@ | |
| * | |
| * 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. |
| + | * At the time of this writing this was considered a feature. |
| + | */ |
| #include "libbb.h" | |
| #include <linux/sockios.h> | |
| #include <net/if.h> | |
| @@ -15,72 +18,129 @@ | |
| #endif | |
| #define ENABLE_FEATURE_BRCTL_SHOW 0 | |
| #define USE_FEATURE_BRCTL_SHOW(...) | |
| - | |
| - | |
| - | /* Fancy diagnostics -- printing add/del -- costs 49 bytes. */ |
| #if 0 | |
| - | #define BRCTL_VERBOSE(...) __VA_ARGS__ |
| + | #define ENABLE_FEATURE_BRCTL_FANCY 0 |
| + | #if ENABLE_FEATURE_BRCTL_FANCY |
| + | #define USE_FEATURE_BRCTL_FANCY(...) __VA_ARGS__ |
| #else | |
| - | #define BRCTL_VERBOSE(...) |
| + | #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 */ |
| + | static inline ALWAYS_INLINE void strtotimeval(struct timeval *tv, |
| + | const char *time_str) |
| + | { |
| + | double secs; |
| + | if (sscanf(time_str, "%lf", &secs) != 1) |
| + | bb_error_msg_and_die (bb_msg_invalid_arg, time_str, "timespec"); |
| + | tv->tv_sec = secs; |
| + | tv->tv_usec = 1000000 * (secs - tv->tv_sec); |
| + | } |
| + | |
| + | static inline ALWAYS_INLINE unsigned long __tv_to_jiffies(const struct timeval *tv) |
| + | { |
| + | unsigned long long jif; |
| + | |
| + | jif = 1000000ULL * tv->tv_sec + tv->tv_usec; |
| + | |
| + | return jif/10000; |
| + | } |
| + | # ifdef UNUSED && 00 |
| + | static void __jiffies_to_tv(struct timeval *tv, unsigned long jiffies) |
| + | { |
| + | unsigned long long tvusec; |
| + | |
| + | tvusec = 10000ULL*jiffies; |
| + | tv->tv_sec = tvusec/1000000; |
| + | tv->tv_usec = tvusec - 1000000 * tv->tv_sec; |
| + | } |
| + | # endif |
| + | static unsigned long str_to_jiffies(const char *time_str) |
| + | { |
| + | struct timeval tv; |
| + | strtotimeval(&tv, time_str); |
| + | return __tv_to_jiffies(&tv); |
| + | } |
| #endif | |
| - | int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| - | int brctl_main(int argc, char **argv) |
| + | |
| + | int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| + | int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv) |
| { | |
| int fd; | |
| static const char keywords[] ALIGN1 = | |
| "addbr\0" "delbr\0" "addif\0" "delif\0" | |
| - | USE_FEATURE_BRCTL_SHOW("show\0"); |
| - | enum { ARG_addbr = 1, ARG_delbr, ARG_addif, ARG_delif |
| - | USE_FEATURE_BRCTL_SHOW(, ARG_show) }; |
| - | smalluint key; |
| - | static char info[] = BRCTL_VERBOSE("%s ")"bridge %s\0 iface %s"; |
| + | USE_FEATURE_BRCTL_FANCY( |
| + | "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_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, |
| + | ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio, |
| + | ARG_stp |
| + | ) |
| + | USE_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) }; |
| + | smallint key; |
| + | struct ifreq ifr; |
| + | static char info[] = "bridge %s\0 iface %s"; |
| char *br; | |
| argv++; | |
| while (*argv) { | |
| - | BRCTL_VERBOSE(char *op;) |
| - | |
| - | key = index_in_strings(keywords, *argv) + 1; |
| - | if (key == 0) /* no match found in keywords array, bail out. */ |
| + | key = index_in_strings(keywords, *argv); |
| + | if (key == -1) /* no match found in keywords array, bail out. */ |
| bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); | |
| argv++; | |
| #if ENABLE_FEATURE_BRCTL_SHOW | |
| if (key == ARG_show) { /* show */ | |
| - | ; |
| + | goto out; /* FIXME: implement me! :) */ |
| } | |
| #endif | |
| - | BRCTL_VERBOSE(op = (char*)((key % 2) ? "add" : "del");) |
| fd = xsocket(AF_INET, SOCK_STREAM, 0); | |
| br = *(argv++); | |
| - | if (key < 3) { /* addbr or delbr */ |
| - | if (ioctl(fd, key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, br) < 0) |
| - | { |
| - | info[9 BRCTL_VERBOSE(+3)] = '\0'; |
| - | bb_perror_msg_and_die(info, BRCTL_VERBOSE(op,) br); |
| - | } |
| + | if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */ |
| + | ioctl_or_perror_and_die(fd, |
| + | key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, |
| + | br, info, br); |
| + | goto done; |
| } | |
| - | if (key > 2) { /* addif or delif */ |
| - | struct ifreq ifr; |
| + | if (!*argv) /* all but 'show' need at least one argument */ |
| + | bb_show_usage(); |
| + | safe_strncpy(ifr.ifr_name, br, IFNAMSIZ); |
| + | if (key == ARG_addif || key == ARG_delif) { /* addif or delif */ |
| char *brif; | |
| - | if (!*argv) |
| - | bb_show_usage(); |
| brif = *(argv++); | |
| - | |
| if (!(ifr.ifr_ifindex = if_nametoindex(brif))) { | |
| - | bb_perror_msg_and_die(info+11 BRCTL_VERBOSE(+3), brif); |
| - | } |
| - | safe_strncpy(ifr.ifr_name, br, IFNAMSIZ); |
| - | if (ioctl(fd, |
| - | key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, &ifr) < 0) { |
| - | info[9 BRCTL_VERBOSE(+3)] = ','; |
| - | bb_perror_msg_and_die (info, BRCTL_VERBOSE(op,) br, brif); |
| + | bb_perror_msg_and_die(info+11, brif); |
| } | |
| + | ioctl_or_perror_and_die(fd, |
| + | key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, |
| + | &ifr, info, br); |
| + | } |
| + | #if ENABLE_FEATURE_BRCTL_FANCY |
| + | if (key - ARG_delif < 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; |
| + | xioctl(fd, SIOCDEVPRIVATE, &ifr); |
| } | |
| + | #endif |
| + | done: |
| if (ENABLE_FEATURE_CLEAN_UP) | |
| close(fd); | |
| } | |
| + | out: |
| return EXIT_SUCCESS; | |
| } | |