brctl: make "show" command retrieve data from /sys
ioctl interface is obsolete and has no 32/64 compat shim, making "brctl show" fail for 32-bit userspace and 64-bit kernel. function old new delta show_bridge - 310 +310 read_file - 64 +64 if_indextoname 117 - -117 brctl_main 1183 885 -298 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 0/1 up/down: 374/-415) Total: -41 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
e2026381be
commit
c5150e9ce7
@ -67,6 +67,7 @@
|
||||
//usage: )
|
||||
|
||||
#include "libbb.h"
|
||||
#include "common_bufsiz.h"
|
||||
#include <linux/sockios.h>
|
||||
#include <net/if.h>
|
||||
|
||||
@ -198,6 +199,69 @@ static void arm_ioctl(unsigned long *args,
|
||||
}
|
||||
#endif
|
||||
|
||||
#define filedata bb_common_bufsiz1
|
||||
static int read_file(const char *name)
|
||||
{
|
||||
int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1);
|
||||
if (n < 0) {
|
||||
filedata[0] = '\0';
|
||||
} else {
|
||||
filedata[n] = '\0';
|
||||
if (n != 0 && filedata[n - 1] == '\n')
|
||||
filedata[--n] = '\0';
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* NB: we are in /sys/class/net
|
||||
*/
|
||||
static int show_bridge(const char *name, int need_hdr)
|
||||
{
|
||||
// Output:
|
||||
//bridge name bridge id STP enabled interfaces
|
||||
//br0 8000.000000000000 no eth0
|
||||
char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 32];
|
||||
int tabs;
|
||||
DIR *ifaces;
|
||||
struct dirent *ent;
|
||||
char *sfx;
|
||||
|
||||
sfx = pathbuf + sprintf(pathbuf, "%s/bridge/", name);
|
||||
strcpy(sfx, "bridge_id");
|
||||
if (read_file(pathbuf) < 0)
|
||||
return -1; /* this iface is not a bridge */
|
||||
|
||||
if (need_hdr)
|
||||
puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces");
|
||||
printf("%s\t\t", name);
|
||||
printf("%s\t", filedata);
|
||||
|
||||
strcpy(sfx, "stp_state");
|
||||
read_file(pathbuf);
|
||||
if (LONE_CHAR(filedata, '0'))
|
||||
strcpy(filedata, "no");
|
||||
else
|
||||
if (LONE_CHAR(filedata, '1'))
|
||||
strcpy(filedata, "yes");
|
||||
printf(filedata);
|
||||
|
||||
strcpy(sfx, "brif");
|
||||
tabs = 0;
|
||||
ifaces = opendir(pathbuf);
|
||||
if (ifaces) {
|
||||
while ((ent = readdir(ifaces)) != NULL) {
|
||||
if (tabs)
|
||||
printf("\t\t\t\t\t");
|
||||
else
|
||||
tabs = 1;
|
||||
printf("\t\t%s\n", ent->d_name);
|
||||
}
|
||||
closedir(ifaces);
|
||||
}
|
||||
if (!tabs) /* bridge has no interfaces */
|
||||
bb_putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||
int brctl_main(int argc UNUSED_PARAM, char **argv)
|
||||
@ -226,6 +290,13 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
|
||||
char *br, *brif;
|
||||
|
||||
argv++;
|
||||
if (!*argv) {
|
||||
/* bare "brctl" shows --help */
|
||||
bb_show_usage();
|
||||
}
|
||||
|
||||
xchdir("/sys/class/net");
|
||||
|
||||
while (*argv) {
|
||||
#if ENABLE_FEATURE_BRCTL_FANCY
|
||||
int ifidx[MAX_PORTS];
|
||||
@ -237,68 +308,50 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
|
||||
if (key == -1) /* no match found in keywords array, bail out. */
|
||||
bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
|
||||
argv++;
|
||||
fd = xsocket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
#if ENABLE_FEATURE_BRCTL_SHOW
|
||||
if (key == ARG_show) { /* show */
|
||||
char buf[IFNAMSIZ];
|
||||
int bridx[MAX_PORTS];
|
||||
int i, num;
|
||||
arm_ioctl(args, BRCTL_GET_BRIDGES,
|
||||
(unsigned long) bridx, MAX_PORTS);
|
||||
num = xioctl(fd, SIOCGIFBR, args);
|
||||
puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces");
|
||||
for (i = 0; i < num; i++) {
|
||||
int j, tabs;
|
||||
struct __bridge_info bi;
|
||||
unsigned char *x;
|
||||
DIR *net;
|
||||
struct dirent *ent;
|
||||
int need_hdr = 1;
|
||||
int exitcode = EXIT_SUCCESS;
|
||||
|
||||
if (!if_indextoname(bridx[i], buf))
|
||||
bb_perror_msg_and_die("can't get bridge name for index %d", i);
|
||||
strncpy_IFNAMSIZ(ifr.ifr_name, buf);
|
||||
|
||||
arm_ioctl(args, BRCTL_GET_BRIDGE_INFO,
|
||||
(unsigned long) &bi, 0);
|
||||
xioctl(fd, SIOCDEVPRIVATE, &ifr);
|
||||
printf("%s\t\t", buf);
|
||||
|
||||
/* print bridge id */
|
||||
x = (unsigned char *) &bi.bridge_id;
|
||||
for (j = 0; j < 8; j++) {
|
||||
printf("%02x", x[j]);
|
||||
if (j == 1)
|
||||
bb_putchar('.');
|
||||
}
|
||||
printf(bi.stp_enabled ? "\tyes" : "\tno");
|
||||
|
||||
/* print interface list */
|
||||
arm_ioctl(args, BRCTL_GET_PORT_LIST,
|
||||
(unsigned long) ifidx, MAX_PORTS);
|
||||
xioctl(fd, SIOCDEVPRIVATE, &ifr);
|
||||
tabs = 0;
|
||||
for (j = 0; j < MAX_PORTS; j++) {
|
||||
if (!ifidx[j])
|
||||
continue;
|
||||
if (!if_indextoname(ifidx[j], buf))
|
||||
bb_perror_msg_and_die("can't get interface name for index %d", j);
|
||||
if (tabs)
|
||||
printf("\t\t\t\t\t");
|
||||
else
|
||||
tabs = 1;
|
||||
printf("\t\t%s\n", buf);
|
||||
}
|
||||
if (!tabs) /* bridge has no interfaces */
|
||||
bb_putchar('\n');
|
||||
if (*argv) {
|
||||
/* "brctl show BR1 BR2 BR3" */
|
||||
do {
|
||||
if (show_bridge(*argv, need_hdr) >= 0) {
|
||||
need_hdr = 0;
|
||||
} else {
|
||||
bb_error_msg("bridge %s does not exist", *argv);
|
||||
//TODO: if device exists, but is not a BR, brctl from bridge-utils 1.6 says this instead:
|
||||
// "device eth0 is not a bridge"
|
||||
exitcode = EXIT_FAILURE;
|
||||
}
|
||||
} while (*++argv != NULL);
|
||||
return exitcode;
|
||||
}
|
||||
goto done;
|
||||
|
||||
/* "brctl show" (if no ifaces, shows nothing, not even header) */
|
||||
net = xopendir(".");
|
||||
while ((ent = readdir(net)) != NULL) {
|
||||
if (DOT_OR_DOTDOT(ent->d_name))
|
||||
continue; /* . or .. */
|
||||
if (show_bridge(ent->d_name, need_hdr) >= 0)
|
||||
need_hdr = 0;
|
||||
}
|
||||
closedir(net);
|
||||
return exitcode;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!*argv) /* all but 'show' need at least one argument */
|
||||
bb_show_usage();
|
||||
|
||||
fd = xsocket(AF_INET, SOCK_STREAM, 0);
|
||||
br = *argv++;
|
||||
|
||||
//brctl from bridge-utils 1.6 also still uses ioctl
|
||||
//for SIOCBRADDBR / SIOCBRDELBR, not /sys accesses
|
||||
if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */
|
||||
ioctl_or_perror_and_die(fd,
|
||||
key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR,
|
||||
@ -329,6 +382,8 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
|
||||
int onoff = index_in_strings(no_yes, *argv);
|
||||
if (onoff < 0)
|
||||
bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
|
||||
//TODO: replace with:
|
||||
//write "0\n" or "1\n" to /sys/class/net/BR/bridge/stp_state
|
||||
onoff = (unsigned)onoff / 4;
|
||||
arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0);
|
||||
goto fire;
|
||||
@ -340,6 +395,11 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
|
||||
BRCTL_SET_BRIDGE_HELLO_TIME, /* ARG_sethello */
|
||||
BRCTL_SET_BRIDGE_MAX_AGE /* ARG_setmaxage */
|
||||
};
|
||||
//TODO: replace with:
|
||||
//setageing BR N: write "N*100\n" to /sys/class/net/BR/bridge/ageing_time
|
||||
//setfd BR N: write "N*100\n" to /sys/class/net/BR/bridge/forward_delay
|
||||
//sethello BR N: write "N*100\n" to /sys/class/net/BR/bridge/hello_time
|
||||
//setmaxage BR N: write "N*100\n" to /sys/class/net/BR/bridge/max_age
|
||||
arm_ioctl(args, ops[key - ARG_setageing], str_to_jiffies(*argv), 0);
|
||||
goto fire;
|
||||
}
|
||||
@ -355,6 +415,11 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
|
||||
int port = -1;
|
||||
unsigned arg1, arg2;
|
||||
|
||||
//TODO: replace with:
|
||||
//setbridgeprio BR N: write "N\n" to /sys/class/net/BR/bridge/priority
|
||||
//setpathcost BR PORT N: ??
|
||||
//setportprio BR PORT N: ??
|
||||
|
||||
if (key != ARG_setbridgeprio) {
|
||||
/* get portnum */
|
||||
unsigned i;
|
||||
|
Loading…
Reference in New Issue
Block a user