1 /* vi: set sw=4 ts=4: */
3 * Small implementation of brctl for busybox.
5 * Copyright (C) 2008 by Bernhard Fischer
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 /* This applet currently uses only the ioctl interface and no sysfs at all.
10 * At the time of this writing this was considered a feature.
13 #include <linux/sockios.h>
16 #ifdef ENABLE_FEATURE_BRCTL_SHOW
19 #define ENABLE_FEATURE_BRCTL_SHOW 0
20 #define USE_FEATURE_BRCTL_SHOW(...)
22 #define ENABLE_FEATURE_BRCTL_FANCY 0
23 #if ENABLE_FEATURE_BRCTL_FANCY
24 #define USE_FEATURE_BRCTL_FANCY(...) __VA_ARGS__
26 #define USE_FEATURE_BRCTL_FANCY(...)
29 #if ENABLE_FEATURE_BRCTL_FANCY
30 #include <linux/if_bridge.h>
31 /* FIXME: These 4 funcs are not really clean and could be improved */
32 static inline ALWAYS_INLINE void strtotimeval(struct timeval *tv,
36 if (sscanf(time_str, "%lf", &secs) != 1)
37 bb_error_msg_and_die (bb_msg_invalid_arg, time_str, "timespec");
39 tv->tv_usec = 1000000 * (secs - tv->tv_sec);
42 static inline ALWAYS_INLINE unsigned long __tv_to_jiffies(const struct timeval *tv)
44 unsigned long long jif;
46 jif = 1000000ULL * tv->tv_sec + tv->tv_usec;
51 static void __jiffies_to_tv(struct timeval *tv, unsigned long jiffies)
53 unsigned long long tvusec;
55 tvusec = 10000ULL*jiffies;
56 tv->tv_sec = tvusec/1000000;
57 tv->tv_usec = tvusec - 1000000 * tv->tv_sec;
60 static unsigned long str_to_jiffies(const char *time_str)
63 strtotimeval(&tv, time_str);
64 return __tv_to_jiffies(&tv);
69 int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv) MAIN_EXTERNALLY_VISIBLE;
70 int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv)
73 static const char keywords[] ALIGN1 =
74 "addbr\0" "delbr\0" "addif\0" "delif\0"
75 USE_FEATURE_BRCTL_FANCY(
76 "setageing\0" "setfd\0" "sethello\0" "setmaxage\0"
77 "setpathcost\0" "setportprio\0" "setbridgeprio\0"
80 USE_FEATURE_BRCTL_SHOW("showmacs\0" "show\0");
81 enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
82 USE_FEATURE_BRCTL_FANCY(,
83 ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
84 ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio,
87 USE_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) };
90 static char info[] = "bridge %s\0 iface %s";
95 key = index_in_strings(keywords, *argv);
96 if (key == -1) /* no match found in keywords array, bail out. */
97 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
99 #if ENABLE_FEATURE_BRCTL_SHOW
100 if (key == ARG_show) { /* show */
101 goto out; /* FIXME: implement me! :) */
104 fd = xsocket(AF_INET, SOCK_STREAM, 0);
107 if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */
108 ioctl_or_perror_and_die(fd,
109 key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR,
113 if (!*argv) /* all but 'show' need at least one argument */
115 safe_strncpy(ifr.ifr_name, br, IFNAMSIZ);
116 if (key == ARG_addif || key == ARG_delif) { /* addif or delif */
120 if (!(ifr.ifr_ifindex = if_nametoindex(brif))) {
121 bb_perror_msg_and_die(info+11, brif);
123 ioctl_or_perror_and_die(fd,
124 key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF,
127 #if ENABLE_FEATURE_BRCTL_FANCY
128 if (key - ARG_delif < 5) { /* time related ops */
129 unsigned long op = (key == ARG_setageing) ? BRCTL_SET_AGEING_TIME :
130 (key == ARG_setfd) ? BRCTL_SET_BRIDGE_FORWARD_DELAY:
131 (key == ARG_sethello) ? BRCTL_SET_BRIDGE_HELLO_TIME:
132 (key == ARG_setmaxage) ? BRCTL_SET_BRIDGE_MAX_AGE :
133 -1/*will never be used */;
134 unsigned long jiff = str_to_jiffies (*(argv++));
135 unsigned long args[4] = {op, jiff, 0, 0};
136 ifr.ifr_data = (char *) &args;
137 xioctl(fd, SIOCDEVPRIVATE, &ifr);
141 if (ENABLE_FEATURE_CLEAN_UP)