diff options
author | Jan Luebbe <jluebbe@debian.org> | 2018-02-14 14:05:27 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-02-20 19:43:32 +0100 |
commit | e789c3bea18181723c4ae7d761ec30926d182cfb (patch) | |
tree | a1d5abfc03412982db4d538c0ad424a46c91f4ac | |
parent | 79cda9522ad390f1bdb7ba1025b1c81bbd1613e6 (diff) | |
download | busybox-w32-e789c3bea18181723c4ae7d761ec30926d182cfb.tar.gz busybox-w32-e789c3bea18181723c4ae7d761ec30926d182cfb.tar.bz2 busybox-w32-e789c3bea18181723c4ae7d761ec30926d182cfb.zip |
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 665f9bcce..accf90759 100644 --- a/networking/ip.c +++ b/networking/ip.c | |||
@@ -156,7 +156,8 @@ | |||
156 | //--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 | 156 | //--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 |
157 | //usage:#define iplink_trivial_usage | 157 | //usage:#define iplink_trivial_usage |
158 | //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" | 158 | //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" |
159 | //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]" | 159 | //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" |
160 | //usage: " [master IFACE | nomaster]\n" | ||
160 | // * short help shows only "set" command, long help continues (with just one "\n") | 161 | // * short help shows only "set" command, long help continues (with just one "\n") |
161 | // * and shows all other commands: | 162 | // * and shows all other commands: |
162 | //usage:#define iplink_full_usage "\n" | 163 | //usage:#define iplink_full_usage "\n" |
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index 312283318..2aa8b683b 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c | |||
@@ -128,6 +128,31 @@ static void set_mtu(char *dev, int mtu) | |||
128 | } | 128 | } |
129 | 129 | ||
130 | /* Exits on error */ | 130 | /* Exits on error */ |
131 | static void set_master(char *dev, int master) | ||
132 | { | ||
133 | struct rtnl_handle rth; | ||
134 | struct { | ||
135 | struct nlmsghdr n; | ||
136 | struct ifinfomsg i; | ||
137 | char buf[1024]; | ||
138 | } req; | ||
139 | |||
140 | memset(&req, 0, sizeof(req)); | ||
141 | |||
142 | req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); | ||
143 | req.n.nlmsg_flags = NLM_F_REQUEST; | ||
144 | req.n.nlmsg_type = RTM_NEWLINK; | ||
145 | req.i.ifi_family = preferred_family; | ||
146 | |||
147 | xrtnl_open(&rth); | ||
148 | req.i.ifi_index = xll_name_to_index(dev); | ||
149 | //printf("master %i for %i\n", master, req.i.ifi_index); | ||
150 | addattr_l(&req.n, sizeof(req), IFLA_MASTER, &master, 4); | ||
151 | if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) | ||
152 | xfunc_die(); | ||
153 | } | ||
154 | |||
155 | /* Exits on error */ | ||
131 | static int get_address(char *dev, int *htype) | 156 | static int get_address(char *dev, int *htype) |
132 | { | 157 | { |
133 | struct ifreq ifr; | 158 | struct ifreq ifr; |
@@ -200,6 +225,7 @@ static int do_set(char **argv) | |||
200 | uint32_t flags = 0; | 225 | uint32_t flags = 0; |
201 | int qlen = -1; | 226 | int qlen = -1; |
202 | int mtu = -1; | 227 | int mtu = -1; |
228 | int master = -1; | ||
203 | char *newaddr = NULL; | 229 | char *newaddr = NULL; |
204 | char *newbrd = NULL; | 230 | char *newbrd = NULL; |
205 | struct ifreq ifr0, ifr1; | 231 | struct ifreq ifr0, ifr1; |
@@ -209,9 +235,11 @@ static int do_set(char **argv) | |||
209 | static const char keywords[] ALIGN1 = | 235 | static const char keywords[] ALIGN1 = |
210 | "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" | 236 | "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" |
211 | "arp\0""promisc\0""address\0" | 237 | "arp\0""promisc\0""address\0" |
238 | "master\0""nomaster\0" | ||
212 | "dev\0" /* must be last */; | 239 | "dev\0" /* must be last */; |
213 | enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, | 240 | enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, |
214 | ARG_arp, ARG_promisc, ARG_addr, | 241 | ARG_arp, ARG_promisc, ARG_addr, |
242 | ARG_master, ARG_nomaster, | ||
215 | ARG_dev }; | 243 | ARG_dev }; |
216 | enum { PARM_on = 0, PARM_off }; | 244 | enum { PARM_on = 0, PARM_off }; |
217 | smalluint key; | 245 | smalluint key; |
@@ -243,6 +271,11 @@ static int do_set(char **argv) | |||
243 | } else if (key == ARG_addr) { | 271 | } else if (key == ARG_addr) { |
244 | NEXT_ARG(); | 272 | NEXT_ARG(); |
245 | newaddr = *argv; | 273 | newaddr = *argv; |
274 | } else if (key == ARG_master) { | ||
275 | NEXT_ARG(); | ||
276 | master = xll_name_to_index(*argv); | ||
277 | } else if (key == ARG_nomaster) { | ||
278 | master = 0; | ||
246 | } else if (key >= ARG_dev) { | 279 | } else if (key >= ARG_dev) { |
247 | /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ | 280 | /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ |
248 | if (key == ARG_dev) { | 281 | if (key == ARG_dev) { |
@@ -427,6 +460,9 @@ static int do_set(char **argv) | |||
427 | if (mtu != -1) { | 460 | if (mtu != -1) { |
428 | set_mtu(dev, mtu); | 461 | set_mtu(dev, mtu); |
429 | } | 462 | } |
463 | if (master != -1) { | ||
464 | set_master(dev, master); | ||
465 | } | ||
430 | if (mask) | 466 | if (mask) |
431 | do_chflags(dev, flags, mask); | 467 | do_chflags(dev, flags, mask); |
432 | return 0; | 468 | return 0; |
@@ -673,6 +709,8 @@ int FAST_FUNC do_iplink(char **argv) | |||
673 | { | 709 | { |
674 | static const char keywords[] ALIGN1 = | 710 | static const char keywords[] ALIGN1 = |
675 | "add\0""delete\0""set\0""show\0""lst\0""list\0"; | 711 | "add\0""delete\0""set\0""show\0""lst\0""list\0"; |
712 | |||
713 | xfunc_error_retval = 2; //TODO: move up to "ip"? Is it the common rule for all "ip" tools? | ||
676 | if (*argv) { | 714 | if (*argv) { |
677 | int key = index_in_substrings(keywords, *argv); | 715 | int key = index_in_substrings(keywords, *argv); |
678 | if (key < 0) /* invalid argument */ | 716 | if (key < 0) /* invalid argument */ |
diff --git a/networking/tcpudp.c b/networking/tcpudp.c index d4c69e0f7..2feb63a01 100644 --- a/networking/tcpudp.c +++ b/networking/tcpudp.c | |||
@@ -318,7 +318,7 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv) | |||
318 | sslser = user; | 318 | sslser = user; |
319 | client = 0; | 319 | client = 0; |
320 | if ((getuid() == 0) && !(opts & OPT_u)) { | 320 | if ((getuid() == 0) && !(opts & OPT_u)) { |
321 | xfunc_exitcode = 100; | 321 | xfunc_error_retval = 100; |
322 | bb_error_msg_and_die(bb_msg_you_must_be_root); | 322 | bb_error_msg_and_die(bb_msg_you_must_be_root); |
323 | } | 323 | } |
324 | if (opts & OPT_u) | 324 | if (opts & OPT_u) |