aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2013-07-15 05:16:13 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2013-07-15 05:16:13 +0200
commita7ecbed56bb620a0e8cd79372886d0fdfeb362c8 (patch)
tree3942b2949f651325b064237861f8d4c2b4243bdb
parent9b58fe9c0b7b10bca17f033d7928e65ab5065fc9 (diff)
downloadbusybox-w32-a7ecbed56bb620a0e8cd79372886d0fdfeb362c8.tar.gz
busybox-w32-a7ecbed56bb620a0e8cd79372886d0fdfeb362c8.tar.bz2
busybox-w32-a7ecbed56bb620a0e8cd79372886d0fdfeb362c8.zip
ip link: add VLAN support
function old new delta do_add_or_delete - 1073 +1073 get_u16 - 62 +62 static.protocols - 16 +16 do_iplink 1235 1232 -3 do_change 495 - -495 ------------------------------------------------------------------------------ (add/remove: 3/1 grow/shrink: 0/1 up/down: 1151/-498) Total: 653 bytes Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/libiproute/iplink.c137
1 files changed, 128 insertions, 9 deletions
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c
index bad2017fe..45cad711b 100644
--- a/networking/libiproute/iplink.c
+++ b/networking/libiproute/iplink.c
@@ -1,6 +1,7 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 3 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
4 * Patrick McHardy <kaber@trash.net>
4 * 5 *
5 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
6 */ 7 */
@@ -9,6 +10,20 @@
9#include <netpacket/packet.h> 10#include <netpacket/packet.h>
10#include <netinet/if_ether.h> 11#include <netinet/if_ether.h>
11 12
13#include <linux/if_vlan.h>
14#undef ETH_P_8021AD
15#define ETH_P_8021AD 0x88A8
16#undef VLAN_FLAG_REORDER_HDR
17#define VLAN_FLAG_REORDER_HDR 0x1
18#undef VLAN_FLAG_GVRP
19#define VLAN_FLAG_GVRP 0x2
20#undef VLAN_FLAG_LOOSE_BINDING
21#define VLAN_FLAG_LOOSE_BINDING 0x4
22#undef VLAN_FLAG_MVRP
23#define VLAN_FLAG_MVRP 0x8
24#undef IFLA_VLAN_PROTOCOL
25#define IFLA_VLAN_PROTOCOL 5
26
12#include "ip_common.h" /* #include "libbb.h" is inside */ 27#include "ip_common.h" /* #include "libbb.h" is inside */
13#include "rt_names.h" 28#include "rt_names.h"
14#include "utils.h" 29#include "utils.h"
@@ -277,12 +292,103 @@ static int ipaddr_list_link(char **argv)
277 return ipaddr_list_or_flush(argv, 0); 292 return ipaddr_list_or_flush(argv, 0);
278} 293}
279 294
295static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
296{
297 static const char keywords[] ALIGN1 =
298 "id\0"
299 "protocol\0"
300 "reorder_hdr\0"
301 "gvrp\0"
302 "mvrp\0"
303 "loose_binding\0"
304 ;
305 static const char protocols[] ALIGN1 =
306 "802.1q\0"
307 "802.1ad\0"
308 ;
309 static const char str_on_off[] ALIGN1 =
310 "on\0"
311 "off\0"
312 ;
313 enum {
314 ARG_id = 0,
315 ARG_reorder_hdr,
316 ARG_gvrp,
317 ARG_mvrp,
318 ARG_loose_binding,
319 ARG_protocol,
320 };
321 enum {
322 PROTO_8021Q = 0,
323 PROTO_8021AD,
324 };
325 enum {
326 PARM_on = 0,
327 PARM_off
328 };
329 int arg;
330 uint16_t id, proto;
331 struct ifla_vlan_flags flags = {};
332
333 while (*argv) {
334 arg = index_in_substrings(keywords, *argv);
335 if (arg < 0)
336 invarg(*argv, "type vlan");
337
338 NEXT_ARG();
339 if (arg == ARG_id) {
340 id = get_u16(*argv, "id");
341 addattr_l(n, size, IFLA_VLAN_ID, &id, sizeof(id));
342 } else if (arg == ARG_protocol) {
343 arg = index_in_substrings(protocols, *argv);
344 if (arg == PROTO_8021Q)
345 proto = ETH_P_8021Q;
346 else if (arg == PROTO_8021AD)
347 proto = ETH_P_8021AD;
348 else
349 bb_error_msg_and_die("unknown VLAN encapsulation protocol '%s'",
350 *argv);
351 addattr_l(n, size, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto));
352 } else {
353 int param = index_in_strings(str_on_off, *argv);
354 if (param < 0)
355 die_must_be_on_off(nth_string(keywords, arg));
356
357 if (arg == ARG_reorder_hdr) {
358 flags.mask |= VLAN_FLAG_REORDER_HDR;
359 flags.flags &= ~VLAN_FLAG_REORDER_HDR;
360 if (param == PARM_on)
361 flags.flags |= VLAN_FLAG_REORDER_HDR;
362 } else if (arg == ARG_gvrp) {
363 flags.mask |= VLAN_FLAG_GVRP;
364 flags.flags &= ~VLAN_FLAG_GVRP;
365 if (param == PARM_on)
366 flags.flags |= VLAN_FLAG_GVRP;
367 } else if (arg == ARG_mvrp) {
368 flags.mask |= VLAN_FLAG_MVRP;
369 flags.flags &= ~VLAN_FLAG_MVRP;
370 if (param == PARM_on)
371 flags.flags |= VLAN_FLAG_MVRP;
372 } else { /*if (arg == ARG_loose_binding) */
373 flags.mask |= VLAN_FLAG_LOOSE_BINDING;
374 flags.flags &= ~VLAN_FLAG_LOOSE_BINDING;
375 if (param == PARM_on)
376 flags.flags |= VLAN_FLAG_LOOSE_BINDING;
377 }
378 }
379 argv++;
380 }
381
382 if (flags.mask)
383 addattr_l(n, size, IFLA_VLAN_FLAGS, &flags, sizeof(flags));
384}
385
280#ifndef NLMSG_TAIL 386#ifndef NLMSG_TAIL
281#define NLMSG_TAIL(nmsg) \ 387#define NLMSG_TAIL(nmsg) \
282 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) 388 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
283#endif 389#endif
284/* Return value becomes exitcode. It's okay to not return at all */ 390/* Return value becomes exitcode. It's okay to not return at all */
285static int do_change(char **argv, const unsigned rtm) 391static int do_add_or_delete(char **argv, const unsigned rtm)
286{ 392{
287 static const char keywords[] ALIGN1 = 393 static const char keywords[] ALIGN1 =
288 "link\0""name\0""type\0""dev\0"; 394 "link\0""name\0""type\0""dev\0";
@@ -312,15 +418,17 @@ static int do_change(char **argv, const unsigned rtm)
312 418
313 while (*argv) { 419 while (*argv) {
314 arg = index_in_substrings(keywords, *argv); 420 arg = index_in_substrings(keywords, *argv);
421 if (arg == ARG_type) {
422 NEXT_ARG();
423 type_str = *argv++;
424 break;
425 }
315 if (arg == ARG_link) { 426 if (arg == ARG_link) {
316 NEXT_ARG(); 427 NEXT_ARG();
317 link_str = *argv; 428 link_str = *argv;
318 } else if (arg == ARG_name) { 429 } else if (arg == ARG_name) {
319 NEXT_ARG(); 430 NEXT_ARG();
320 name_str = *argv; 431 name_str = *argv;
321 } else if (arg == ARG_type) {
322 NEXT_ARG();
323 type_str = *argv;
324 } else { 432 } else {
325 if (arg == ARG_dev) { 433 if (arg == ARG_dev) {
326 if (dev_str) 434 if (dev_str)
@@ -339,6 +447,17 @@ static int do_change(char **argv, const unsigned rtm)
339 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); 447 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
340 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str, 448 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str,
341 strlen(type_str)); 449 strlen(type_str));
450
451 if (*argv) {
452 struct rtattr *data = NLMSG_TAIL(&req.n);
453 addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
454
455 if (strcmp(type_str, "vlan") == 0)
456 vlan_parse_opt(argv, &req.n, sizeof(req));
457
458 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
459 }
460
342 linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; 461 linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
343 } 462 }
344 if (rtm != RTM_NEWLINK) { 463 if (rtm != RTM_NEWLINK) {
@@ -370,13 +489,13 @@ int FAST_FUNC do_iplink(char **argv)
370 static const char keywords[] ALIGN1 = 489 static const char keywords[] ALIGN1 =
371 "add\0""delete\0""set\0""show\0""lst\0""list\0"; 490 "add\0""delete\0""set\0""show\0""lst\0""list\0";
372 if (*argv) { 491 if (*argv) {
373 smalluint key = index_in_substrings(keywords, *argv); 492 int key = index_in_substrings(keywords, *argv);
374 if (key > 5) /* invalid argument */ 493 if (key < 0) /* invalid argument */
375 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); 494 invarg(*argv, applet_name);
376 argv++; 495 argv++;
377 if (key <= 1) /* add/delete */ 496 if (key <= 1) /* add/delete */
378 return do_change(argv, key ? RTM_DELLINK : RTM_NEWLINK); 497 return do_add_or_delete(argv, key ? RTM_DELLINK : RTM_NEWLINK);
379 else if (key == 2) /* set */ 498 if (key == 2) /* set */
380 return do_set(argv); 499 return do_set(argv);
381 } 500 }
382 /* show, lst, list */ 501 /* show, lst, list */