]> Pileus Git - ~andy/linux/blobdiff - net/core/rtnetlink.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireles...
[~andy/linux] / net / core / rtnetlink.c
index 02cf848f71d23205b79384361af3fde819517fd3..2bd9c5f7627dd84b450ec3f105263979adda77e3 100644 (file)
@@ -82,32 +82,6 @@ int rtnl_trylock(void)
        return mutex_trylock(&rtnl_mutex);
 }
 
-int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
-{
-       memset(tb, 0, sizeof(struct rtattr*)*maxattr);
-
-       while (RTA_OK(rta, len)) {
-               unsigned flavor = rta->rta_type;
-               if (flavor && flavor <= maxattr)
-                       tb[flavor-1] = rta;
-               rta = RTA_NEXT(rta, len);
-       }
-       return 0;
-}
-
-int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
-                                struct rtattr *rta, int len)
-{
-       if (RTA_PAYLOAD(rta) < len)
-               return -1;
-       if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
-               rta = RTA_DATA(rta) + RTA_ALIGN(len);
-               return rtattr_parse_nested(tb, maxattr, rta);
-       }
-       memset(tb, 0, sizeof(struct rtattr *) * maxattr);
-       return 0;
-}
-
 static struct rtnl_link *rtnl_msg_handlers[NPROTO];
 
 static inline int rtm_msgindex(int msgtype)
@@ -442,21 +416,6 @@ void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data
        memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size);
 }
 
-size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size)
-{
-       size_t ret = RTA_PAYLOAD(rta);
-       char *src = RTA_DATA(rta);
-
-       if (ret > 0 && src[ret - 1] == '\0')
-               ret--;
-       if (size > 0) {
-               size_t len = (ret >= size) ? size - 1 : ret;
-               memset(dest, 0, size);
-               memcpy(dest, src, len);
-       }
-       return ret;
-}
-
 int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo)
 {
        struct sock *rtnl = net->rtnl;
@@ -730,10 +689,12 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
        [IFLA_BROADCAST]        = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
        [IFLA_MAP]              = { .len = sizeof(struct rtnl_link_ifmap) },
        [IFLA_MTU]              = { .type = NLA_U32 },
+       [IFLA_LINK]             = { .type = NLA_U32 },
        [IFLA_TXQLEN]           = { .type = NLA_U32 },
        [IFLA_WEIGHT]           = { .type = NLA_U32 },
        [IFLA_OPERSTATE]        = { .type = NLA_U8 },
        [IFLA_LINKMODE]         = { .type = NLA_U8 },
+       [IFLA_LINKINFO]         = { .type = NLA_NESTED },
        [IFLA_NET_NS_PID]       = { .type = NLA_U32 },
 };
 
@@ -761,6 +722,21 @@ static struct net *get_net_ns_by_pid(pid_t pid)
        return net;
 }
 
+static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
+{
+       if (dev) {
+               if (tb[IFLA_ADDRESS] &&
+                   nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
+                       return -EINVAL;
+
+               if (tb[IFLA_BROADCAST] &&
+                   nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
                      struct nlattr **tb, char *ifname, int modified)
 {
@@ -933,12 +909,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
                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)
+       if ((err = validate_linkmsg(dev, tb)) < 0)
                goto errout_dev;
 
        err = do_setlink(dev, ifm, tb, ifname, 0);
@@ -1059,6 +1030,9 @@ replay:
        else
                dev = NULL;
 
+       if ((err = validate_linkmsg(dev, tb)) < 0)
+               return err;
+
        if (tb[IFLA_LINKINFO]) {
                err = nla_parse_nested(linkinfo, IFLA_INFO_MAX,
                                       tb[IFLA_LINKINFO], ifla_info_policy);
@@ -1368,25 +1342,14 @@ static int rtnetlink_net_init(struct net *net)
                                   rtnetlink_rcv, &rtnl_mutex, THIS_MODULE);
        if (!sk)
                return -ENOMEM;
-
-       /* Don't hold an extra reference on the namespace */
-       put_net(sk->sk_net);
        net->rtnl = sk;
        return 0;
 }
 
 static void rtnetlink_net_exit(struct net *net)
 {
-       struct sock *sk = net->rtnl;
-       if (sk) {
-               /* At the last minute lie and say this is a socket for the
-                * initial network namespace.  So the socket will be safe to
-                * free.
-                */
-               sk->sk_net = get_net(&init_net);
-               netlink_kernel_release(net->rtnl);
-               net->rtnl = NULL;
-       }
+       netlink_kernel_release(net->rtnl);
+       net->rtnl = NULL;
 }
 
 static struct pernet_operations rtnetlink_net_ops = {
@@ -1422,9 +1385,6 @@ void __init rtnetlink_init(void)
 }
 
 EXPORT_SYMBOL(__rta_fill);
-EXPORT_SYMBOL(rtattr_strlcpy);
-EXPORT_SYMBOL(rtattr_parse);
-EXPORT_SYMBOL(__rtattr_parse_nested_compat);
 EXPORT_SYMBOL(rtnetlink_put_metrics);
 EXPORT_SYMBOL(rtnl_lock);
 EXPORT_SYMBOL(rtnl_trylock);