aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/usage.h4
-rw-r--r--networking/Config.in1
-rw-r--r--networking/brctl.c113
3 files changed, 97 insertions, 21 deletions
diff --git a/include/usage.h b/include/usage.h
index 304899d18..3e019718a 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -133,6 +133,10 @@ USE_FEATURE_BRCTL_FANCY("\n" \
133 " setfd <bridge <time> set bridge forward delay\n" \ 133 " setfd <bridge <time> set bridge forward delay\n" \
134 " sethello <bridge <time> set hello time\n" \ 134 " sethello <bridge <time> set hello time\n" \
135 " setmaxage <bridge <time> set max message age\n" \ 135 " setmaxage <bridge <time> set max message age\n" \
136 " setpathcost <bridge <cost> set path cost\n" \
137 " setportprio <bridge <prio> set port priority\n" \
138 " setbridgeprio <bridge <prio> set bridge priority\n" \
139 " stp <bridge> [1|0] turn stp on/off\n" \
136) 140)
137#define bunzip2_trivial_usage \ 141#define bunzip2_trivial_usage \
138 "[OPTION]... [FILE]" 142 "[OPTION]... [FILE]"
diff --git a/networking/Config.in b/networking/Config.in
index f4d4e7ebf..f1f7ae04b 100644
--- a/networking/Config.in
+++ b/networking/Config.in
@@ -71,6 +71,7 @@ config FEATURE_BRCTL_FANCY
71 setageing, setfd, sethello, setmaxage, 71 setageing, setfd, sethello, setmaxage,
72 setpathcost, setportprio, setbridgeprio, 72 setpathcost, setportprio, setbridgeprio,
73 stp 73 stp
74 This adds about 600 bytes.
74 75
75config DNSD 76config DNSD
76 bool "dnsd" 77 bool "dnsd"
diff --git a/networking/brctl.c b/networking/brctl.c
index 7c9d90fde..bbd14c471 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -4,6 +4,9 @@
4 * 4 *
5 * Copyright (C) 2008 by Bernhard Fischer 5 * Copyright (C) 2008 by Bernhard Fischer
6 * 6 *
7 * Some helper functions from bridge-utils are
8 * Copyright (C) 2000 Lennert Buytenhek
9 *
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 10 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 */ 11 */
9/* This applet currently uses only the ioctl interface and no sysfs at all. 12/* This applet currently uses only the ioctl interface and no sysfs at all.
@@ -13,19 +16,21 @@
13#include <linux/sockios.h> 16#include <linux/sockios.h>
14#include <net/if.h> 17#include <net/if.h>
15 18
19/* Maximum number of ports supported per bridge interface. */
20#ifndef MAX_PORTS
21#define MAX_PORTS 32
22#endif
23
24/* Use internal number parsing and not the "exact" conversion. */
25/* #define BRCTL_USE_INTERNAL 0 */ /* use exact conversion */
26#define BRCTL_USE_INTERNAL 1
27
16#ifdef ENABLE_FEATURE_BRCTL_SHOW 28#ifdef ENABLE_FEATURE_BRCTL_SHOW
17#error Remove these 29#error Remove these
18#endif 30#endif
19#define ENABLE_FEATURE_BRCTL_SHOW 0 31#define ENABLE_FEATURE_BRCTL_SHOW 0
20#define USE_FEATURE_BRCTL_SHOW(...) 32#define USE_FEATURE_BRCTL_SHOW(...)
21#if 0 33
22#define ENABLE_FEATURE_BRCTL_FANCY 0
23#if ENABLE_FEATURE_BRCTL_FANCY
24#define USE_FEATURE_BRCTL_FANCY(...) __VA_ARGS__
25#else
26#define USE_FEATURE_BRCTL_FANCY(...)
27#endif
28#endif
29#if ENABLE_FEATURE_BRCTL_FANCY 34#if ENABLE_FEATURE_BRCTL_FANCY
30#include <linux/if_bridge.h> 35#include <linux/if_bridge.h>
31/* FIXME: These 4 funcs are not really clean and could be improved */ 36/* 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,
33 const char *time_str) 38 const char *time_str)
34{ 39{
35 double secs; 40 double secs;
41#if BRCTL_USE_INTERNAL
42 if (!(secs = /*bb_*/strtod(time_str, NULL)))
43#else
36 if (sscanf(time_str, "%lf", &secs) != 1) 44 if (sscanf(time_str, "%lf", &secs) != 1)
45#endif
37 bb_error_msg_and_die (bb_msg_invalid_arg, time_str, "timespec"); 46 bb_error_msg_and_die (bb_msg_invalid_arg, time_str, "timespec");
38 tv->tv_sec = secs; 47 tv->tv_sec = secs;
39 tv->tv_usec = 1000000 * (secs - tv->tv_sec); 48 tv->tv_usec = 1000000 * (secs - tv->tv_sec);
@@ -47,7 +56,7 @@ static inline ALWAYS_INLINE unsigned long __tv_to_jiffies(const struct timeval *
47 56
48 return jif/10000; 57 return jif/10000;
49} 58}
50# ifdef UNUSED && 00 59# if 00
51static void __jiffies_to_tv(struct timeval *tv, unsigned long jiffies) 60static void __jiffies_to_tv(struct timeval *tv, unsigned long jiffies)
52{ 61{
53 unsigned long long tvusec; 62 unsigned long long tvusec;
@@ -63,6 +72,15 @@ static unsigned long str_to_jiffies(const char *time_str)
63 strtotimeval(&tv, time_str); 72 strtotimeval(&tv, time_str);
64 return __tv_to_jiffies(&tv); 73 return __tv_to_jiffies(&tv);
65} 74}
75
76static void arm_ioctl(unsigned long *args,
77 unsigned long arg0, unsigned long arg1, unsigned long arg2)
78{
79 args[0] = arg0;
80 args[1] = arg1;
81 args[2] = arg2;
82 args[3] = 0;
83}
66#endif 84#endif
67 85
68 86
@@ -73,22 +91,27 @@ int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv)
73 static const char keywords[] ALIGN1 = 91 static const char keywords[] ALIGN1 =
74 "addbr\0" "delbr\0" "addif\0" "delif\0" 92 "addbr\0" "delbr\0" "addif\0" "delif\0"
75 USE_FEATURE_BRCTL_FANCY( 93 USE_FEATURE_BRCTL_FANCY(
94 "stp\0"
76 "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" 95 "setageing\0" "setfd\0" "sethello\0" "setmaxage\0"
77 "setpathcost\0" "setportprio\0" "setbridgeprio\0" 96 "setpathcost\0" "setportprio\0" "setbridgeprio\0"
78 "stp\0"
79 ) 97 )
80 USE_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); 98 USE_FEATURE_BRCTL_SHOW("showmacs\0" "show\0");
81 enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif 99 enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
82 USE_FEATURE_BRCTL_FANCY(, 100 USE_FEATURE_BRCTL_FANCY(,
101 ARG_stp,
83 ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, 102 ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
84 ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio, 103 ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio
85 ARG_stp
86 ) 104 )
87 USE_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) }; 105 USE_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) };
88 smallint key; 106 smallint key;
89 struct ifreq ifr; 107 struct ifreq ifr;
90 static char info[] = "bridge %s\0 iface %s"; 108 static char info[] = "bridge %s\0 iface %s";
91 char *br; 109 char *br, *brif;
110#if ENABLE_FEATURE_BRCTL_FANCY
111 unsigned long args[4] = {0, 0, 0, 0};
112 int port;
113 int tmp;
114#endif
92 115
93 argv++; 116 argv++;
94 while (*argv) { 117 while (*argv) {
@@ -114,8 +137,6 @@ int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv)
114 bb_show_usage(); 137 bb_show_usage();
115 safe_strncpy(ifr.ifr_name, br, IFNAMSIZ); 138 safe_strncpy(ifr.ifr_name, br, IFNAMSIZ);
116 if (key == ARG_addif || key == ARG_delif) { /* addif or delif */ 139 if (key == ARG_addif || key == ARG_delif) { /* addif or delif */
117 char *brif;
118
119 brif = *(argv++); 140 brif = *(argv++);
120 if (!(ifr.ifr_ifindex = if_nametoindex(brif))) { 141 if (!(ifr.ifr_ifindex = if_nametoindex(brif))) {
121 bb_perror_msg_and_die(info+11, brif); 142 bb_perror_msg_and_die(info+11, brif);
@@ -123,24 +144,74 @@ int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv)
123 ioctl_or_perror_and_die(fd, 144 ioctl_or_perror_and_die(fd,
124 key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, 145 key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF,
125 &ifr, info, br); 146 &ifr, info, br);
147 goto done;
126 } 148 }
127#if ENABLE_FEATURE_BRCTL_FANCY 149#if ENABLE_FEATURE_BRCTL_FANCY
128 if (key - ARG_delif < 5) { /* time related ops */ 150 ifr.ifr_data = (char *) &args;
151 if (key == ARG_stp) { /* stp */
152 /* FIXME: parsing yes/y/on/1 versus no/n/off/0 is too involved */
153 arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE,
154 (unsigned)(**argv - '0'), 0);
155 goto fire;
156 }
157 if ((unsigned)(key - ARG_stp) < 5) { /* time related ops */
129 unsigned long op = (key == ARG_setageing) ? BRCTL_SET_AGEING_TIME : 158 unsigned long op = (key == ARG_setageing) ? BRCTL_SET_AGEING_TIME :
130 (key == ARG_setfd) ? BRCTL_SET_BRIDGE_FORWARD_DELAY: 159 (key == ARG_setfd) ? BRCTL_SET_BRIDGE_FORWARD_DELAY:
131 (key == ARG_sethello) ? BRCTL_SET_BRIDGE_HELLO_TIME: 160 (key == ARG_sethello) ? BRCTL_SET_BRIDGE_HELLO_TIME:
132 (key == ARG_setmaxage) ? BRCTL_SET_BRIDGE_MAX_AGE : 161 (key == ARG_setmaxage) ? BRCTL_SET_BRIDGE_MAX_AGE :
133 -1/*will never be used */; 162 -1/* will never be used */;
134 unsigned long jiff = str_to_jiffies (*(argv++)); 163 arm_ioctl(args, op, str_to_jiffies (*argv), 0);
135 unsigned long args[4] = {op, jiff, 0, 0}; 164 goto fire;
136 ifr.ifr_data = (char *) &args; 165 }
166 port = -1;
167 if (key == ARG_setpathcost || key == ARG_setportprio) {/* get portnum */
168 int ifidx[MAX_PORTS];
169 unsigned i;
170
171 if (!(port = if_nametoindex(*argv)))
172 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, "port");
173 argv++;
174 memset(ifidx, 0, sizeof ifidx);
175 arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx,
176 MAX_PORTS);
137 xioctl(fd, SIOCDEVPRIVATE, &ifr); 177 xioctl(fd, SIOCDEVPRIVATE, &ifr);
178 for (i = 0; i < MAX_PORTS; i++)
179 if (ifidx[i] == port) {
180 port = i;
181 break;
182 }
138 } 183 }
184 if (key == ARG_setpathcost
185 || key == ARG_setportprio || key == ARG_setbridgeprio) {
186 unsigned long op = (key == ARG_setpathcost) ? BRCTL_SET_PATH_COST :
187 (key == ARG_setportprio) ? BRCTL_SET_PORT_PRIORITY :
188 (key == ARG_setbridgeprio) ? BRCTL_SET_BRIDGE_PRIORITY :
189 -1/* will never be used */;
190 unsigned long arg1 = port;
191 unsigned long arg2;
192# if BRCTL_USE_INTERNAL
193 tmp = xatoi(*argv);
194# else
195 if (sscanf(*argv, "%i", &tmp) != 1)
196 bb_error_msg_and_die(bb_msg_invalid_arg, *argv,
197 key == ARG_setpathcost ? "cost" : "prio");
198# endif
199 if (key == ARG_setbridgeprio) {
200 arg1 = tmp;
201 arg2 = 0;
202 } else
203 arg2 = tmp;
204 arm_ioctl(args, op, arg1, arg2);
205 }
206 fire:
207 /* Execute the previously set command. */
208 xioctl(fd, SIOCDEVPRIVATE, &ifr);
209 argv++;
139#endif 210#endif
140 done: 211 done:
141 if (ENABLE_FEATURE_CLEAN_UP) 212 if (ENABLE_FEATURE_CLEAN_UP)
142 close(fd); 213 close(fd);
143 } 214 }
144 out: 215USE_FEATURE_BRCTL_SHOW(out:)
145 return EXIT_SUCCESS; 216 return EXIT_SUCCESS;
146} 217}