aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/brctl.c163
1 files changed, 114 insertions, 49 deletions
diff --git a/networking/brctl.c b/networking/brctl.c
index ba4a714f8..706ecfc07 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -67,6 +67,7 @@
67//usage: ) 67//usage: )
68 68
69#include "libbb.h" 69#include "libbb.h"
70#include "common_bufsiz.h"
70#include <linux/sockios.h> 71#include <linux/sockios.h>
71#include <net/if.h> 72#include <net/if.h>
72 73
@@ -198,6 +199,69 @@ static void arm_ioctl(unsigned long *args,
198} 199}
199#endif 200#endif
200 201
202#define filedata bb_common_bufsiz1
203static int read_file(const char *name)
204{
205 int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1);
206 if (n < 0) {
207 filedata[0] = '\0';
208 } else {
209 filedata[n] = '\0';
210 if (n != 0 && filedata[n - 1] == '\n')
211 filedata[--n] = '\0';
212 }
213 return n;
214}
215
216/* NB: we are in /sys/class/net
217 */
218static int show_bridge(const char *name, int need_hdr)
219{
220// Output:
221//bridge name bridge id STP enabled interfaces
222//br0 8000.000000000000 no eth0
223 char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 32];
224 int tabs;
225 DIR *ifaces;
226 struct dirent *ent;
227 char *sfx;
228
229 sfx = pathbuf + sprintf(pathbuf, "%s/bridge/", name);
230 strcpy(sfx, "bridge_id");
231 if (read_file(pathbuf) < 0)
232 return -1; /* this iface is not a bridge */
233
234 if (need_hdr)
235 puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces");
236 printf("%s\t\t", name);
237 printf("%s\t", filedata);
238
239 strcpy(sfx, "stp_state");
240 read_file(pathbuf);
241 if (LONE_CHAR(filedata, '0'))
242 strcpy(filedata, "no");
243 else
244 if (LONE_CHAR(filedata, '1'))
245 strcpy(filedata, "yes");
246 printf(filedata);
247
248 strcpy(sfx, "brif");
249 tabs = 0;
250 ifaces = opendir(pathbuf);
251 if (ifaces) {
252 while ((ent = readdir(ifaces)) != NULL) {
253 if (tabs)
254 printf("\t\t\t\t\t");
255 else
256 tabs = 1;
257 printf("\t\t%s\n", ent->d_name);
258 }
259 closedir(ifaces);
260 }
261 if (!tabs) /* bridge has no interfaces */
262 bb_putchar('\n');
263 return 0;
264}
201 265
202int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 266int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
203int brctl_main(int argc UNUSED_PARAM, char **argv) 267int brctl_main(int argc UNUSED_PARAM, char **argv)
@@ -226,6 +290,13 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
226 char *br, *brif; 290 char *br, *brif;
227 291
228 argv++; 292 argv++;
293 if (!*argv) {
294 /* bare "brctl" shows --help */
295 bb_show_usage();
296 }
297
298 xchdir("/sys/class/net");
299
229 while (*argv) { 300 while (*argv) {
230#if ENABLE_FEATURE_BRCTL_FANCY 301#if ENABLE_FEATURE_BRCTL_FANCY
231 int ifidx[MAX_PORTS]; 302 int ifidx[MAX_PORTS];
@@ -237,68 +308,50 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
237 if (key == -1) /* no match found in keywords array, bail out. */ 308 if (key == -1) /* no match found in keywords array, bail out. */
238 bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); 309 bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
239 argv++; 310 argv++;
240 fd = xsocket(AF_INET, SOCK_STREAM, 0);
241 311
242#if ENABLE_FEATURE_BRCTL_SHOW 312#if ENABLE_FEATURE_BRCTL_SHOW
243 if (key == ARG_show) { /* show */ 313 if (key == ARG_show) { /* show */
244 char buf[IFNAMSIZ]; 314 DIR *net;
245 int bridx[MAX_PORTS]; 315 struct dirent *ent;
246 int i, num; 316 int need_hdr = 1;
247 arm_ioctl(args, BRCTL_GET_BRIDGES, 317 int exitcode = EXIT_SUCCESS;
248 (unsigned long) bridx, MAX_PORTS); 318
249 num = xioctl(fd, SIOCGIFBR, args); 319 if (*argv) {
250 puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces"); 320 /* "brctl show BR1 BR2 BR3" */
251 for (i = 0; i < num; i++) { 321 do {
252 int j, tabs; 322 if (show_bridge(*argv, need_hdr) >= 0) {
253 struct __bridge_info bi; 323 need_hdr = 0;
254 unsigned char *x; 324 } else {
255 325 bb_error_msg("bridge %s does not exist", *argv);
256 if (!if_indextoname(bridx[i], buf)) 326//TODO: if device exists, but is not a BR, brctl from bridge-utils 1.6 says this instead:
257 bb_perror_msg_and_die("can't get bridge name for index %d", i); 327// "device eth0 is not a bridge"
258 strncpy_IFNAMSIZ(ifr.ifr_name, buf); 328 exitcode = EXIT_FAILURE;
259 329 }
260 arm_ioctl(args, BRCTL_GET_BRIDGE_INFO, 330 } while (*++argv != NULL);
261 (unsigned long) &bi, 0); 331 return exitcode;
262 xioctl(fd, SIOCDEVPRIVATE, &ifr); 332 }
263 printf("%s\t\t", buf);
264
265 /* print bridge id */
266 x = (unsigned char *) &bi.bridge_id;
267 for (j = 0; j < 8; j++) {
268 printf("%02x", x[j]);
269 if (j == 1)
270 bb_putchar('.');
271 }
272 printf(bi.stp_enabled ? "\tyes" : "\tno");
273 333
274 /* print interface list */ 334 /* "brctl show" (if no ifaces, shows nothing, not even header) */
275 arm_ioctl(args, BRCTL_GET_PORT_LIST, 335 net = xopendir(".");
276 (unsigned long) ifidx, MAX_PORTS); 336 while ((ent = readdir(net)) != NULL) {
277 xioctl(fd, SIOCDEVPRIVATE, &ifr); 337 if (DOT_OR_DOTDOT(ent->d_name))
278 tabs = 0; 338 continue; /* . or .. */
279 for (j = 0; j < MAX_PORTS; j++) { 339 if (show_bridge(ent->d_name, need_hdr) >= 0)
280 if (!ifidx[j]) 340 need_hdr = 0;
281 continue;
282 if (!if_indextoname(ifidx[j], buf))
283 bb_perror_msg_and_die("can't get interface name for index %d", j);
284 if (tabs)
285 printf("\t\t\t\t\t");
286 else
287 tabs = 1;
288 printf("\t\t%s\n", buf);
289 }
290 if (!tabs) /* bridge has no interfaces */
291 bb_putchar('\n');
292 } 341 }
293 goto done; 342 closedir(net);
343 return exitcode;
294 } 344 }
295#endif 345#endif
296 346
297 if (!*argv) /* all but 'show' need at least one argument */ 347 if (!*argv) /* all but 'show' need at least one argument */
298 bb_show_usage(); 348 bb_show_usage();
299 349
350 fd = xsocket(AF_INET, SOCK_STREAM, 0);
300 br = *argv++; 351 br = *argv++;
301 352
353//brctl from bridge-utils 1.6 also still uses ioctl
354//for SIOCBRADDBR / SIOCBRDELBR, not /sys accesses
302 if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */ 355 if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */
303 ioctl_or_perror_and_die(fd, 356 ioctl_or_perror_and_die(fd,
304 key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, 357 key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR,
@@ -329,6 +382,8 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
329 int onoff = index_in_strings(no_yes, *argv); 382 int onoff = index_in_strings(no_yes, *argv);
330 if (onoff < 0) 383 if (onoff < 0)
331 bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); 384 bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
385//TODO: replace with:
386//write "0\n" or "1\n" to /sys/class/net/BR/bridge/stp_state
332 onoff = (unsigned)onoff / 4; 387 onoff = (unsigned)onoff / 4;
333 arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0); 388 arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0);
334 goto fire; 389 goto fire;
@@ -340,6 +395,11 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
340 BRCTL_SET_BRIDGE_HELLO_TIME, /* ARG_sethello */ 395 BRCTL_SET_BRIDGE_HELLO_TIME, /* ARG_sethello */
341 BRCTL_SET_BRIDGE_MAX_AGE /* ARG_setmaxage */ 396 BRCTL_SET_BRIDGE_MAX_AGE /* ARG_setmaxage */
342 }; 397 };
398//TODO: replace with:
399//setageing BR N: write "N*100\n" to /sys/class/net/BR/bridge/ageing_time
400//setfd BR N: write "N*100\n" to /sys/class/net/BR/bridge/forward_delay
401//sethello BR N: write "N*100\n" to /sys/class/net/BR/bridge/hello_time
402//setmaxage BR N: write "N*100\n" to /sys/class/net/BR/bridge/max_age
343 arm_ioctl(args, ops[key - ARG_setageing], str_to_jiffies(*argv), 0); 403 arm_ioctl(args, ops[key - ARG_setageing], str_to_jiffies(*argv), 0);
344 goto fire; 404 goto fire;
345 } 405 }
@@ -355,6 +415,11 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
355 int port = -1; 415 int port = -1;
356 unsigned arg1, arg2; 416 unsigned arg1, arg2;
357 417
418//TODO: replace with:
419//setbridgeprio BR N: write "N\n" to /sys/class/net/BR/bridge/priority
420//setpathcost BR PORT N: ??
421//setportprio BR PORT N: ??
422
358 if (key != ARG_setbridgeprio) { 423 if (key != ARG_setbridgeprio) {
359 /* get portnum */ 424 /* get portnum */
360 unsigned i; 425 unsigned i;