mirror of
https://github.com/sheumann/hush.git
synced 2024-10-29 20:27:40 +00:00
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>
This commit is contained in:
parent
9b58fe9c0b
commit
a7ecbed56b
@ -1,6 +1,7 @@
|
|||||||
/* vi: set sw=4 ts=4: */
|
/* vi: set sw=4 ts=4: */
|
||||||
/*
|
/*
|
||||||
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
||||||
|
* Patrick McHardy <kaber@trash.net>
|
||||||
*
|
*
|
||||||
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||||
*/
|
*/
|
||||||
@ -9,6 +10,20 @@
|
|||||||
#include <netpacket/packet.h>
|
#include <netpacket/packet.h>
|
||||||
#include <netinet/if_ether.h>
|
#include <netinet/if_ether.h>
|
||||||
|
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
#undef ETH_P_8021AD
|
||||||
|
#define ETH_P_8021AD 0x88A8
|
||||||
|
#undef VLAN_FLAG_REORDER_HDR
|
||||||
|
#define VLAN_FLAG_REORDER_HDR 0x1
|
||||||
|
#undef VLAN_FLAG_GVRP
|
||||||
|
#define VLAN_FLAG_GVRP 0x2
|
||||||
|
#undef VLAN_FLAG_LOOSE_BINDING
|
||||||
|
#define VLAN_FLAG_LOOSE_BINDING 0x4
|
||||||
|
#undef VLAN_FLAG_MVRP
|
||||||
|
#define VLAN_FLAG_MVRP 0x8
|
||||||
|
#undef IFLA_VLAN_PROTOCOL
|
||||||
|
#define IFLA_VLAN_PROTOCOL 5
|
||||||
|
|
||||||
#include "ip_common.h" /* #include "libbb.h" is inside */
|
#include "ip_common.h" /* #include "libbb.h" is inside */
|
||||||
#include "rt_names.h"
|
#include "rt_names.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@ -277,12 +292,103 @@ static int ipaddr_list_link(char **argv)
|
|||||||
return ipaddr_list_or_flush(argv, 0);
|
return ipaddr_list_or_flush(argv, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
|
||||||
|
{
|
||||||
|
static const char keywords[] ALIGN1 =
|
||||||
|
"id\0"
|
||||||
|
"protocol\0"
|
||||||
|
"reorder_hdr\0"
|
||||||
|
"gvrp\0"
|
||||||
|
"mvrp\0"
|
||||||
|
"loose_binding\0"
|
||||||
|
;
|
||||||
|
static const char protocols[] ALIGN1 =
|
||||||
|
"802.1q\0"
|
||||||
|
"802.1ad\0"
|
||||||
|
;
|
||||||
|
static const char str_on_off[] ALIGN1 =
|
||||||
|
"on\0"
|
||||||
|
"off\0"
|
||||||
|
;
|
||||||
|
enum {
|
||||||
|
ARG_id = 0,
|
||||||
|
ARG_reorder_hdr,
|
||||||
|
ARG_gvrp,
|
||||||
|
ARG_mvrp,
|
||||||
|
ARG_loose_binding,
|
||||||
|
ARG_protocol,
|
||||||
|
};
|
||||||
|
enum {
|
||||||
|
PROTO_8021Q = 0,
|
||||||
|
PROTO_8021AD,
|
||||||
|
};
|
||||||
|
enum {
|
||||||
|
PARM_on = 0,
|
||||||
|
PARM_off
|
||||||
|
};
|
||||||
|
int arg;
|
||||||
|
uint16_t id, proto;
|
||||||
|
struct ifla_vlan_flags flags = {};
|
||||||
|
|
||||||
|
while (*argv) {
|
||||||
|
arg = index_in_substrings(keywords, *argv);
|
||||||
|
if (arg < 0)
|
||||||
|
invarg(*argv, "type vlan");
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
if (arg == ARG_id) {
|
||||||
|
id = get_u16(*argv, "id");
|
||||||
|
addattr_l(n, size, IFLA_VLAN_ID, &id, sizeof(id));
|
||||||
|
} else if (arg == ARG_protocol) {
|
||||||
|
arg = index_in_substrings(protocols, *argv);
|
||||||
|
if (arg == PROTO_8021Q)
|
||||||
|
proto = ETH_P_8021Q;
|
||||||
|
else if (arg == PROTO_8021AD)
|
||||||
|
proto = ETH_P_8021AD;
|
||||||
|
else
|
||||||
|
bb_error_msg_and_die("unknown VLAN encapsulation protocol '%s'",
|
||||||
|
*argv);
|
||||||
|
addattr_l(n, size, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto));
|
||||||
|
} else {
|
||||||
|
int param = index_in_strings(str_on_off, *argv);
|
||||||
|
if (param < 0)
|
||||||
|
die_must_be_on_off(nth_string(keywords, arg));
|
||||||
|
|
||||||
|
if (arg == ARG_reorder_hdr) {
|
||||||
|
flags.mask |= VLAN_FLAG_REORDER_HDR;
|
||||||
|
flags.flags &= ~VLAN_FLAG_REORDER_HDR;
|
||||||
|
if (param == PARM_on)
|
||||||
|
flags.flags |= VLAN_FLAG_REORDER_HDR;
|
||||||
|
} else if (arg == ARG_gvrp) {
|
||||||
|
flags.mask |= VLAN_FLAG_GVRP;
|
||||||
|
flags.flags &= ~VLAN_FLAG_GVRP;
|
||||||
|
if (param == PARM_on)
|
||||||
|
flags.flags |= VLAN_FLAG_GVRP;
|
||||||
|
} else if (arg == ARG_mvrp) {
|
||||||
|
flags.mask |= VLAN_FLAG_MVRP;
|
||||||
|
flags.flags &= ~VLAN_FLAG_MVRP;
|
||||||
|
if (param == PARM_on)
|
||||||
|
flags.flags |= VLAN_FLAG_MVRP;
|
||||||
|
} else { /*if (arg == ARG_loose_binding) */
|
||||||
|
flags.mask |= VLAN_FLAG_LOOSE_BINDING;
|
||||||
|
flags.flags &= ~VLAN_FLAG_LOOSE_BINDING;
|
||||||
|
if (param == PARM_on)
|
||||||
|
flags.flags |= VLAN_FLAG_LOOSE_BINDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags.mask)
|
||||||
|
addattr_l(n, size, IFLA_VLAN_FLAGS, &flags, sizeof(flags));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NLMSG_TAIL
|
#ifndef NLMSG_TAIL
|
||||||
#define NLMSG_TAIL(nmsg) \
|
#define NLMSG_TAIL(nmsg) \
|
||||||
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||||
#endif
|
#endif
|
||||||
/* Return value becomes exitcode. It's okay to not return at all */
|
/* Return value becomes exitcode. It's okay to not return at all */
|
||||||
static int do_change(char **argv, const unsigned rtm)
|
static int do_add_or_delete(char **argv, const unsigned rtm)
|
||||||
{
|
{
|
||||||
static const char keywords[] ALIGN1 =
|
static const char keywords[] ALIGN1 =
|
||||||
"link\0""name\0""type\0""dev\0";
|
"link\0""name\0""type\0""dev\0";
|
||||||
@ -312,15 +418,17 @@ static int do_change(char **argv, const unsigned rtm)
|
|||||||
|
|
||||||
while (*argv) {
|
while (*argv) {
|
||||||
arg = index_in_substrings(keywords, *argv);
|
arg = index_in_substrings(keywords, *argv);
|
||||||
|
if (arg == ARG_type) {
|
||||||
|
NEXT_ARG();
|
||||||
|
type_str = *argv++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (arg == ARG_link) {
|
if (arg == ARG_link) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
link_str = *argv;
|
link_str = *argv;
|
||||||
} else if (arg == ARG_name) {
|
} else if (arg == ARG_name) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
name_str = *argv;
|
name_str = *argv;
|
||||||
} else if (arg == ARG_type) {
|
|
||||||
NEXT_ARG();
|
|
||||||
type_str = *argv;
|
|
||||||
} else {
|
} else {
|
||||||
if (arg == ARG_dev) {
|
if (arg == ARG_dev) {
|
||||||
if (dev_str)
|
if (dev_str)
|
||||||
@ -339,6 +447,17 @@ static int do_change(char **argv, const unsigned rtm)
|
|||||||
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
|
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
|
||||||
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str,
|
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str,
|
||||||
strlen(type_str));
|
strlen(type_str));
|
||||||
|
|
||||||
|
if (*argv) {
|
||||||
|
struct rtattr *data = NLMSG_TAIL(&req.n);
|
||||||
|
addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
|
||||||
|
|
||||||
|
if (strcmp(type_str, "vlan") == 0)
|
||||||
|
vlan_parse_opt(argv, &req.n, sizeof(req));
|
||||||
|
|
||||||
|
data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
|
||||||
|
}
|
||||||
|
|
||||||
linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
|
linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
|
||||||
}
|
}
|
||||||
if (rtm != RTM_NEWLINK) {
|
if (rtm != RTM_NEWLINK) {
|
||||||
@ -370,13 +489,13 @@ int FAST_FUNC do_iplink(char **argv)
|
|||||||
static const char keywords[] ALIGN1 =
|
static const char keywords[] ALIGN1 =
|
||||||
"add\0""delete\0""set\0""show\0""lst\0""list\0";
|
"add\0""delete\0""set\0""show\0""lst\0""list\0";
|
||||||
if (*argv) {
|
if (*argv) {
|
||||||
smalluint key = index_in_substrings(keywords, *argv);
|
int key = index_in_substrings(keywords, *argv);
|
||||||
if (key > 5) /* invalid argument */
|
if (key < 0) /* invalid argument */
|
||||||
bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
|
invarg(*argv, applet_name);
|
||||||
argv++;
|
argv++;
|
||||||
if (key <= 1) /* add/delete */
|
if (key <= 1) /* add/delete */
|
||||||
return do_change(argv, key ? RTM_DELLINK : RTM_NEWLINK);
|
return do_add_or_delete(argv, key ? RTM_DELLINK : RTM_NEWLINK);
|
||||||
else if (key == 2) /* set */
|
if (key == 2) /* set */
|
||||||
return do_set(argv);
|
return do_set(argv);
|
||||||
}
|
}
|
||||||
/* show, lst, list */
|
/* show, lst, list */
|
||||||
|
Loading…
Reference in New Issue
Block a user