diff options
author | Jan Luebbe | 2018-02-14 14:05:27 +0100 |
---|---|---|
committer | Denys Vlasenko | 2018-02-20 19:43:32 +0100 |
commit | e789c3bea18181723c4ae7d761ec30926d182cfb (patch) | |
tree | a1d5abfc03412982db4d538c0ad424a46c91f4ac | |
parent | 79cda9522ad390f1bdb7ba1025b1c81bbd1613e6 (diff) | |
download | busybox-e789c3bea18181723c4ae7d761ec30926d182cfb.zip busybox-e789c3bea18181723c4ae7d761ec30926d182cfb.tar.gz |
iplink: implement support for selecting a master interface
Attaching an interface to a VRF is done by setting the interface's
master. Besides VRF, this can also be used for bridges.
function old new delta
set_master - 142 +142
do_iplink 1262 1357 +95
packed_usage 32546 32539 -7
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/1 up/down: 237/-7) Total: 230 bytes
Signed-off-by: Jan Luebbe <jluebbe@debian.org>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/ip.c | 3 | ||||
-rw-r--r-- | networking/libiproute/iplink.c | 38 | ||||
-rw-r--r-- | networking/tcpudp.c | 2 |
3 files changed, 41 insertions, 2 deletions
diff --git a/networking/ip.c b/networking/ip.c index 665f9bc..accf907 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -156,7 +156,8 @@ //--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 //usage:#define iplink_trivial_usage //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" -//usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]" +//usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" +//usage: " [master IFACE | nomaster]\n" // * short help shows only "set" command, long help continues (with just one "\n") // * and shows all other commands: //usage:#define iplink_full_usage "\n" diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index 3122833..2aa8b68 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c @@ -128,6 +128,31 @@ static void set_mtu(char *dev, int mtu) } /* Exits on error */ +static void set_master(char *dev, int master) +{ + struct rtnl_handle rth; + struct { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[1024]; + } req; + + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_NEWLINK; + req.i.ifi_family = preferred_family; + + xrtnl_open(&rth); + req.i.ifi_index = xll_name_to_index(dev); + //printf("master %i for %i\n", master, req.i.ifi_index); + addattr_l(&req.n, sizeof(req), IFLA_MASTER, &master, 4); + if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) + xfunc_die(); +} + +/* Exits on error */ static int get_address(char *dev, int *htype) { struct ifreq ifr; @@ -200,6 +225,7 @@ static int do_set(char **argv) uint32_t flags = 0; int qlen = -1; int mtu = -1; + int master = -1; char *newaddr = NULL; char *newbrd = NULL; struct ifreq ifr0, ifr1; @@ -209,9 +235,11 @@ static int do_set(char **argv) static const char keywords[] ALIGN1 = "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" "arp\0""promisc\0""address\0" + "master\0""nomaster\0" "dev\0" /* must be last */; enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, ARG_arp, ARG_promisc, ARG_addr, + ARG_master, ARG_nomaster, ARG_dev }; enum { PARM_on = 0, PARM_off }; smalluint key; @@ -243,6 +271,11 @@ static int do_set(char **argv) } else if (key == ARG_addr) { NEXT_ARG(); newaddr = *argv; + } else if (key == ARG_master) { + NEXT_ARG(); + master = xll_name_to_index(*argv); + } else if (key == ARG_nomaster) { + master = 0; } else if (key >= ARG_dev) { /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ if (key == ARG_dev) { @@ -427,6 +460,9 @@ static int do_set(char **argv) if (mtu != -1) { set_mtu(dev, mtu); } + if (master != -1) { + set_master(dev, master); + } if (mask) do_chflags(dev, flags, mask); return 0; @@ -673,6 +709,8 @@ int FAST_FUNC do_iplink(char **argv) { static const char keywords[] ALIGN1 = "add\0""delete\0""set\0""show\0""lst\0""list\0"; + + xfunc_error_retval = 2; //TODO: move up to "ip"? Is it the common rule for all "ip" tools? if (*argv) { int key = index_in_substrings(keywords, *argv); if (key < 0) /* invalid argument */ diff --git a/networking/tcpudp.c b/networking/tcpudp.c index d4c69e0..2feb63a 100644 --- a/networking/tcpudp.c +++ b/networking/tcpudp.c @@ -318,7 +318,7 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv) sslser = user; client = 0; if ((getuid() == 0) && !(opts & OPT_u)) { - xfunc_exitcode = 100; + xfunc_error_retval = 100; bb_error_msg_and_die(bb_msg_you_must_be_root); } if (opts & OPT_u) |