Commit 0157f60c authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[RTNETLINK]: Split up rtnl_setlink

Split up rtnl_setlink into a function performing validation and a function
performing the actual changes. This allows to share the modifcation logic
with rtnl_newlink, which is introduced by the next patch.
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6472ce60
...@@ -561,44 +561,11 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = { ...@@ -561,44 +561,11 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_LINKMODE] = { .type = NLA_U8 }, [IFLA_LINKMODE] = { .type = NLA_U8 },
}; };
static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
struct nlattr **tb, char *ifname)
{ {
struct ifinfomsg *ifm; int modified = 0, send_addr_notify = 0;
struct net_device *dev; int err;
int err, send_addr_notify = 0, modified = 0;
struct nlattr *tb[IFLA_MAX+1];
char ifname[IFNAMSIZ];
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
if (err < 0)
goto errout;
if (tb[IFLA_IFNAME])
nla_strlcpy(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(ifm->ifi_index);
else if (tb[IFLA_IFNAME])
dev = dev_get_by_name(ifname);
else
goto errout;
if (dev == NULL) {
err = -ENODEV;
goto errout;
}
if (tb[IFLA_ADDRESS] &&
nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
goto errout_dev;
if (tb[IFLA_BROADCAST] &&
nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
goto errout_dev;
if (tb[IFLA_MAP]) { if (tb[IFLA_MAP]) {
struct rtnl_link_ifmap *u_map; struct rtnl_link_ifmap *u_map;
...@@ -606,12 +573,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -606,12 +573,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (!dev->set_config) { if (!dev->set_config) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto errout_dev; goto errout;
} }
if (!netif_device_present(dev)) { if (!netif_device_present(dev)) {
err = -ENODEV; err = -ENODEV;
goto errout_dev; goto errout;
} }
u_map = nla_data(tb[IFLA_MAP]); u_map = nla_data(tb[IFLA_MAP]);
...@@ -624,7 +591,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -624,7 +591,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = dev->set_config(dev, &k_map); err = dev->set_config(dev, &k_map);
if (err < 0) if (err < 0)
goto errout_dev; goto errout;
modified = 1; modified = 1;
} }
...@@ -635,19 +602,19 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -635,19 +602,19 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (!dev->set_mac_address) { if (!dev->set_mac_address) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto errout_dev; goto errout;
} }
if (!netif_device_present(dev)) { if (!netif_device_present(dev)) {
err = -ENODEV; err = -ENODEV;
goto errout_dev; goto errout;
} }
len = sizeof(sa_family_t) + dev->addr_len; len = sizeof(sa_family_t) + dev->addr_len;
sa = kmalloc(len, GFP_KERNEL); sa = kmalloc(len, GFP_KERNEL);
if (!sa) { if (!sa) {
err = -ENOMEM; err = -ENOMEM;
goto errout_dev; goto errout;
} }
sa->sa_family = dev->type; sa->sa_family = dev->type;
memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
...@@ -655,7 +622,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -655,7 +622,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = dev->set_mac_address(dev, sa); err = dev->set_mac_address(dev, sa);
kfree(sa); kfree(sa);
if (err) if (err)
goto errout_dev; goto errout;
send_addr_notify = 1; send_addr_notify = 1;
modified = 1; modified = 1;
} }
...@@ -663,7 +630,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -663,7 +630,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (tb[IFLA_MTU]) { if (tb[IFLA_MTU]) {
err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
if (err < 0) if (err < 0)
goto errout_dev; goto errout;
modified = 1; modified = 1;
} }
...@@ -675,7 +642,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -675,7 +642,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (ifm->ifi_index > 0 && ifname[0]) { if (ifm->ifi_index > 0 && ifname[0]) {
err = dev_change_name(dev, ifname); err = dev_change_name(dev, ifname);
if (err < 0) if (err < 0)
goto errout_dev; goto errout;
modified = 1; modified = 1;
} }
...@@ -684,7 +651,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -684,7 +651,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
send_addr_notify = 1; send_addr_notify = 1;
} }
if (ifm->ifi_flags || ifm->ifi_change) { if (ifm->ifi_flags || ifm->ifi_change) {
unsigned int flags = ifm->ifi_flags; unsigned int flags = ifm->ifi_flags;
...@@ -712,7 +678,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -712,7 +678,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = 0; err = 0;
errout_dev: errout:
if (err < 0 && modified && net_ratelimit()) if (err < 0 && modified && net_ratelimit())
printk(KERN_WARNING "A link change request failed with " printk(KERN_WARNING "A link change request failed with "
"some changes comitted already. Interface %s may " "some changes comitted already. Interface %s may "
...@@ -721,7 +687,50 @@ errout_dev: ...@@ -721,7 +687,50 @@ errout_dev:
if (send_addr_notify) if (send_addr_notify)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
return err;
}
static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct ifinfomsg *ifm;
struct net_device *dev;
int err;
struct nlattr *tb[IFLA_MAX+1];
char ifname[IFNAMSIZ];
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
if (err < 0)
goto errout;
if (tb[IFLA_IFNAME])
nla_strlcpy(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(ifm->ifi_index);
else if (tb[IFLA_IFNAME])
dev = dev_get_by_name(ifname);
else
goto errout;
if (dev == NULL) {
err = -ENODEV;
goto errout;
}
if (tb[IFLA_ADDRESS] &&
nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
goto errout_dev;
if (tb[IFLA_BROADCAST] &&
nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
goto errout_dev;
err = do_setlink(dev, ifm, tb, ifname);
errout_dev:
dev_put(dev); dev_put(dev);
errout: errout:
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment