Commit 5ea08b52 authored by Florent Fourcot's avatar Florent Fourcot Committed by Paolo Abeni
Browse files

rtnetlink: enable alt_ifname for setlink/newlink



buffer called "ifname" given in function rtnl_dev_get
is always valid when called by setlink/newlink,
but contains only empty string when IFLA_IFNAME is not given. So
IFLA_ALT_IFNAME is always ignored

This patch fixes rtnl_dev_get function with a remove of ifname argument,
and move ifname copy in do_setlink when required.

It extends feature of commit 76c9ac0e,
"net: rtnetlink: add possibility to use alternative names as message
handle""

CC: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarFlorent Fourcot <florent.fourcot@wifirst.fr>
Signed-off-by: default avatarBrian Baboch <brian.baboch@wifirst.fr>
Reviewed-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent ef2a7c90
Loading
Loading
Loading
Loading
+29 −40
Original line number Diff line number Diff line
@@ -2644,17 +2644,23 @@ static int do_set_proto_down(struct net_device *dev,
static int do_setlink(const struct sk_buff *skb,
		      struct net_device *dev, struct ifinfomsg *ifm,
		      struct netlink_ext_ack *extack,
		      struct nlattr **tb, char *ifname, int status)
		      struct nlattr **tb, int status)
{
	const struct net_device_ops *ops = dev->netdev_ops;
	char ifname[IFNAMSIZ];
	int err;

	err = validate_linkmsg(dev, tb, extack);
	if (err < 0)
		return err;

	if (tb[IFLA_IFNAME])
		nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
	else
		ifname[0] = '\0';

	if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD] || tb[IFLA_TARGET_NETNSID]) {
		const char *pat = ifname && ifname[0] ? ifname : NULL;
		const char *pat = ifname[0] ? ifname : NULL;
		struct net *net;
		int new_ifindex;

@@ -3010,21 +3016,16 @@ static int do_setlink(const struct sk_buff *skb,
}

static struct net_device *rtnl_dev_get(struct net *net,
				       struct nlattr *ifname_attr,
				       struct nlattr *altifname_attr,
				       char *ifname)
{
	char buffer[ALTIFNAMSIZ];

	if (!ifname) {
		ifname = buffer;
		if (ifname_attr)
			nla_strscpy(ifname, ifname_attr, IFNAMSIZ);
		else if (altifname_attr)
			nla_strscpy(ifname, altifname_attr, ALTIFNAMSIZ);
				       struct nlattr *tb[])
{
	char ifname[ALTIFNAMSIZ];

	if (tb[IFLA_IFNAME])
		nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
	else if (tb[IFLA_ALT_IFNAME])
		nla_strscpy(ifname, tb[IFLA_ALT_IFNAME], ALTIFNAMSIZ);
	else
		return NULL;
	}

	return __dev_get_by_name(net, ifname);
}
@@ -3037,7 +3038,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
	struct net_device *dev;
	int err;
	struct nlattr *tb[IFLA_MAX+1];
	char ifname[IFNAMSIZ];

	err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX,
				     ifla_policy, extack);
@@ -3048,17 +3048,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
	if (err < 0)
		goto errout;

	if (tb[IFLA_IFNAME])
		nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
	else
		ifname[0] = '\0';

	err = -EINVAL;
	ifm = nlmsg_data(nlh);
	if (ifm->ifi_index > 0)
		dev = __dev_get_by_index(net, ifm->ifi_index);
	else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
		dev = rtnl_dev_get(net, NULL, tb[IFLA_ALT_IFNAME], ifname);
		dev = rtnl_dev_get(net, tb);
	else
		goto errout;

@@ -3067,7 +3062,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
		goto errout;
	}

	err = do_setlink(skb, dev, ifm, extack, tb, ifname, 0);
	err = do_setlink(skb, dev, ifm, extack, tb, 0);
errout:
	return err;
}
@@ -3156,8 +3151,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
	if (ifm->ifi_index > 0)
		dev = __dev_get_by_index(tgt_net, ifm->ifi_index);
	else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
		dev = rtnl_dev_get(net, tb[IFLA_IFNAME],
				   tb[IFLA_ALT_IFNAME], NULL);
		dev = rtnl_dev_get(net, tb);
	else if (tb[IFLA_GROUP])
		err = rtnl_group_dellink(tgt_net, nla_get_u32(tb[IFLA_GROUP]));
	else
@@ -3299,7 +3293,7 @@ static int rtnl_group_changelink(const struct sk_buff *skb,

	for_each_netdev_safe(net, dev, aux) {
		if (dev->group == group) {
			err = do_setlink(skb, dev, ifm, extack, tb, NULL, 0);
			err = do_setlink(skb, dev, ifm, extack, tb, 0);
			if (err < 0)
				return err;
		}
@@ -3341,18 +3335,13 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
	if (err < 0)
		return err;

	if (tb[IFLA_IFNAME])
		nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
	else
		ifname[0] = '\0';

	ifm = nlmsg_data(nlh);
	if (ifm->ifi_index > 0) {
		link_specified = true;
		dev = __dev_get_by_index(net, ifm->ifi_index);
	} else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) {
		link_specified = true;
		dev = rtnl_dev_get(net, NULL, tb[IFLA_ALT_IFNAME], ifname);
		dev = rtnl_dev_get(net, tb);
	} else {
		link_specified = false;
		dev = NULL;
@@ -3455,7 +3444,7 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
			status |= DO_SETLINK_NOTIFY;
		}

		return do_setlink(skb, dev, ifm, extack, tb, ifname, status);
		return do_setlink(skb, dev, ifm, extack, tb, status);
	}

	if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
@@ -3492,7 +3481,9 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
	if (!ops->alloc && !ops->setup)
		return -EOPNOTSUPP;

	if (!ifname[0]) {
	if (tb[IFLA_IFNAME]) {
		nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
	} else {
		snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
		name_assign_type = NET_NAME_ENUM;
	}
@@ -3664,8 +3655,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
	if (ifm->ifi_index > 0)
		dev = __dev_get_by_index(tgt_net, ifm->ifi_index);
	else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
		dev = rtnl_dev_get(tgt_net, tb[IFLA_IFNAME],
				   tb[IFLA_ALT_IFNAME], NULL);
		dev = rtnl_dev_get(tgt_net, tb);
	else
		goto out;

@@ -3760,8 +3750,7 @@ static int rtnl_linkprop(int cmd, struct sk_buff *skb, struct nlmsghdr *nlh,
	if (ifm->ifi_index > 0)
		dev = __dev_get_by_index(net, ifm->ifi_index);
	else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
		dev = rtnl_dev_get(net, tb[IFLA_IFNAME],
				   tb[IFLA_ALT_IFNAME], NULL);
		dev = rtnl_dev_get(net, tb);
	else
		return -EINVAL;