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: )
|
//usage: )
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
#include "common_bufsiz.h"
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
|
||||||
@ -198,6 +199,69 @@ static void arm_ioctl(unsigned long *args,
|
|||||||
}
|
}
|
||||||
#endif
|
#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, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int brctl_main(int argc UNUSED_PARAM, char **argv)
|
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;
|
char *br, *brif;
|
||||||
|
|
||||||
argv++;
|
argv++;
|
||||||
|
if (!*argv) {
|
||||||
|
/* bare "brctl" shows --help */
|
||||||
|
bb_show_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
xchdir("/sys/class/net");
|
||||||
|
|
||||||
while (*argv) {
|
while (*argv) {
|
||||||
#if ENABLE_FEATURE_BRCTL_FANCY
|
#if ENABLE_FEATURE_BRCTL_FANCY
|
||||||
int ifidx[MAX_PORTS];
|
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. */
|
if (key == -1) /* no match found in keywords array, bail out. */
|
||||||
bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
|
bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
|
||||||
argv++;
|
argv++;
|
||||||
fd = xsocket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_BRCTL_SHOW
|
#if ENABLE_FEATURE_BRCTL_SHOW
|
||||||
if (key == ARG_show) { /* show */
|
if (key == ARG_show) { /* show */
|
||||||
char buf[IFNAMSIZ];
|
DIR *net;
|
||||||
int bridx[MAX_PORTS];
|
struct dirent *ent;
|
||||||
int i, num;
|
int need_hdr = 1;
|
||||||
arm_ioctl(args, BRCTL_GET_BRIDGES,
|
int exitcode = EXIT_SUCCESS;
|
||||||
(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;
|
|
||||||
|
|
||||||
if (!if_indextoname(bridx[i], buf))
|
if (*argv) {
|
||||||
bb_perror_msg_and_die("can't get bridge name for index %d", i);
|
/* "brctl show BR1 BR2 BR3" */
|
||||||
strncpy_IFNAMSIZ(ifr.ifr_name, buf);
|
do {
|
||||||
|
if (show_bridge(*argv, need_hdr) >= 0) {
|
||||||
arm_ioctl(args, BRCTL_GET_BRIDGE_INFO,
|
need_hdr = 0;
|
||||||
(unsigned long) &bi, 0);
|
} else {
|
||||||
xioctl(fd, SIOCDEVPRIVATE, &ifr);
|
bb_error_msg("bridge %s does not exist", *argv);
|
||||||
printf("%s\t\t", buf);
|
//TODO: if device exists, but is not a BR, brctl from bridge-utils 1.6 says this instead:
|
||||||
|
// "device eth0 is not a bridge"
|
||||||
/* print bridge id */
|
exitcode = EXIT_FAILURE;
|
||||||
x = (unsigned char *) &bi.bridge_id;
|
}
|
||||||
for (j = 0; j < 8; j++) {
|
} while (*++argv != NULL);
|
||||||
printf("%02x", x[j]);
|
return exitcode;
|
||||||
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');
|
|
||||||
}
|
}
|
||||||
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
|
#endif
|
||||||
|
|
||||||
if (!*argv) /* all but 'show' need at least one argument */
|
if (!*argv) /* all but 'show' need at least one argument */
|
||||||
bb_show_usage();
|
bb_show_usage();
|
||||||
|
|
||||||
|
fd = xsocket(AF_INET, SOCK_STREAM, 0);
|
||||||
br = *argv++;
|
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 */
|
if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */
|
||||||
ioctl_or_perror_and_die(fd,
|
ioctl_or_perror_and_die(fd,
|
||||||
key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR,
|
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);
|
int onoff = index_in_strings(no_yes, *argv);
|
||||||
if (onoff < 0)
|
if (onoff < 0)
|
||||||
bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
|
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;
|
onoff = (unsigned)onoff / 4;
|
||||||
arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0);
|
arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0);
|
||||||
goto fire;
|
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_HELLO_TIME, /* ARG_sethello */
|
||||||
BRCTL_SET_BRIDGE_MAX_AGE /* ARG_setmaxage */
|
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);
|
arm_ioctl(args, ops[key - ARG_setageing], str_to_jiffies(*argv), 0);
|
||||||
goto fire;
|
goto fire;
|
||||||
}
|
}
|
||||||
@ -355,6 +415,11 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
int port = -1;
|
int port = -1;
|
||||||
unsigned arg1, arg2;
|
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) {
|
if (key != ARG_setbridgeprio) {
|
||||||
/* get portnum */
|
/* get portnum */
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user