aboutsummaryrefslogtreecommitdiff
path: root/networking/brctl.c
diff options
context:
space:
mode:
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2008-01-14 16:10:11 +0000
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2008-01-14 16:10:11 +0000
commit2b11fb483e663149d79992021cc4e495e0df8677 (patch)
treef5567e7905409192b150afa7dde907264815b7f8 /networking/brctl.c
parentc2f0de5eef4feeca5d993ff3553b0e196862282f (diff)
downloadbusybox-w32-2b11fb483e663149d79992021cc4e495e0df8677.tar.gz
busybox-w32-2b11fb483e663149d79992021cc4e495e0df8677.tar.bz2
busybox-w32-2b11fb483e663149d79992021cc4e495e0df8677.zip
- 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.c113
1 files changed, 92 insertions, 21 deletions
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}