[RTNETLINK]: Split up rtnl_setlink
authorPatrick McHardy <kaber@trash.net>
Wed, 13 Jun 2007 19:03:36 +0000 (12:03 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Wed, 11 Jul 2007 05:14:16 +0000 (22:14 -0700)
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: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/rtnetlink.c

index 02e8bf0..25ca219 100644 (file)
@@ -561,44 +561,11 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
        [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;
-       struct net_device *dev;
-       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;
+       int modified = 0, send_addr_notify = 0;
+       int err;
 
        if (tb[IFLA_MAP]) {
                struct rtnl_link_ifmap *u_map;
@@ -606,12 +573,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 
                if (!dev->set_config) {
                        err = -EOPNOTSUPP;
-                       goto errout_dev;
+                       goto errout;
                }
 
                if (!netif_device_present(dev)) {
                        err = -ENODEV;
-                       goto errout_dev;
+                       goto errout;
                }
 
                u_map = nla_data(tb[IFLA_MAP]);
@@ -624,7 +591,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 
                err = dev->set_config(dev, &k_map);
                if (err < 0)
-                       goto errout_dev;
+                       goto errout;
 
                modified = 1;
        }
@@ -635,19 +602,19 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 
                if (!dev->set_mac_address) {
                        err = -EOPNOTSUPP;
-                       goto errout_dev;
+                       goto errout;
                }
 
                if (!netif_device_present(dev)) {
                        err = -ENODEV;
-                       goto errout_dev;
+                       goto errout;
                }
 
                len = sizeof(sa_family_t) + dev->addr_len;
                sa = kmalloc(len, GFP_KERNEL);
                if (!sa) {
                        err = -ENOMEM;
-                       goto errout_dev;
+                       goto errout;
                }
                sa->sa_family = dev->type;
                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)
                err = dev->set_mac_address(dev, sa);
                kfree(sa);
                if (err)
-                       goto errout_dev;
+                       goto errout;
                send_addr_notify = 1;
                modified = 1;
        }
@@ -663,7 +630,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        if (tb[IFLA_MTU]) {
                err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
                if (err < 0)
-                       goto errout_dev;
+                       goto errout;
                modified = 1;
        }
 
@@ -675,7 +642,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        if (ifm->ifi_index > 0 && ifname[0]) {
                err = dev_change_name(dev, ifname);
                if (err < 0)
-                       goto errout_dev;
+                       goto errout;
                modified = 1;
        }
 
@@ -684,7 +651,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
                send_addr_notify = 1;
        }
 
-
        if (ifm->ifi_flags || ifm->ifi_change) {
                unsigned int flags = ifm->ifi_flags;
 
@@ -712,7 +678,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 
        err = 0;
 
-errout_dev:
+errout:
        if (err < 0 && modified && net_ratelimit())
                printk(KERN_WARNING "A link change request failed with "
                       "some changes comitted already. Interface %s may "
@@ -721,7 +687,50 @@ errout_dev:
 
        if (send_addr_notify)
                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);
 errout:
        return err;