iplink: support add/delete
function old new delta do_change - 490 +490 .rodata 135193 135225 +32 do_iplink 1146 1169 +23 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/0 up/down: 545/0) Total: 545 bytes Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
This commit is contained in:
parent
49ee8393f4
commit
6faebfa663
@ -283,11 +283,98 @@ static int ipaddr_list_link(char **argv)
|
||||
return ipaddr_list_or_flush(argv, 0);
|
||||
}
|
||||
|
||||
#ifndef NLMSG_TAIL
|
||||
#define NLMSG_TAIL(nmsg) \
|
||||
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||
#endif
|
||||
/* Return value becomes exitcode. It's okay to not return at all */
|
||||
static int do_change(char **argv, const unsigned rtm)
|
||||
{
|
||||
static const char keywords[] ALIGN1 =
|
||||
"link\0""name\0""type\0""dev\0";
|
||||
enum {
|
||||
ARG_link,
|
||||
ARG_name,
|
||||
ARG_type,
|
||||
ARG_dev,
|
||||
};
|
||||
struct rtnl_handle rth;
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ifinfomsg i;
|
||||
char buf[1024];
|
||||
} req;
|
||||
int arg;
|
||||
char *name_str = NULL, *link_str = NULL, *type_str = NULL, *dev_str = NULL;
|
||||
|
||||
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;
|
||||
req.i.ifi_family = preferred_family;
|
||||
if (rtm == RTM_NEWLINK)
|
||||
req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
|
||||
|
||||
while (*argv) {
|
||||
arg = index_in_substrings(keywords, *argv);
|
||||
if (arg == ARG_link) {
|
||||
NEXT_ARG();
|
||||
link_str = *argv;
|
||||
} else if (arg == ARG_name) {
|
||||
NEXT_ARG();
|
||||
name_str = *argv;
|
||||
} else if (arg == ARG_type) {
|
||||
NEXT_ARG();
|
||||
type_str = *argv;
|
||||
} else {
|
||||
if (arg == ARG_dev) {
|
||||
if (dev_str)
|
||||
duparg(*argv, "dev");
|
||||
NEXT_ARG();
|
||||
}
|
||||
dev_str = *argv;
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
xrtnl_open(&rth);
|
||||
ll_init_map(&rth);
|
||||
if (type_str) {
|
||||
struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
|
||||
|
||||
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
|
||||
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str,
|
||||
strlen(type_str));
|
||||
linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
|
||||
}
|
||||
if (rtm != RTM_NEWLINK) {
|
||||
if (!dev_str)
|
||||
return 1; /* Need a device to delete */
|
||||
req.i.ifi_index = xll_name_to_index(dev_str);
|
||||
} else {
|
||||
if (!name_str)
|
||||
name_str = dev_str;
|
||||
if (link_str) {
|
||||
int idx = xll_name_to_index(link_str);
|
||||
addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4);
|
||||
}
|
||||
}
|
||||
if (name_str) {
|
||||
const size_t name_len = strlen(name_str) + 1;
|
||||
if (name_len < 2 || name_len > IFNAMSIZ)
|
||||
invarg(name_str, "name");
|
||||
addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len);
|
||||
}
|
||||
if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return value becomes exitcode. It's okay to not return at all */
|
||||
int do_iplink(char **argv)
|
||||
{
|
||||
static const char keywords[] ALIGN1 =
|
||||
"set\0""show\0""lst\0""list\0";
|
||||
"add\0""delete\0""set\0""show\0""lst\0""list\0";
|
||||
int key;
|
||||
if (!*argv)
|
||||
return ipaddr_list_link(argv);
|
||||
@ -295,7 +382,9 @@ int do_iplink(char **argv)
|
||||
if (key < 0)
|
||||
bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
|
||||
argv++;
|
||||
if (key == 0) /* set */
|
||||
if (key <= 1) /* add/delete */
|
||||
return do_change(argv, key ? RTM_DELLINK : RTM_NEWLINK);
|
||||
else if (key == 2) /* set */
|
||||
return do_set(argv);
|
||||
/* show, lst, list */
|
||||
return ipaddr_list_link(argv);
|
||||
|
Loading…
Reference in New Issue
Block a user