[ARM] dma: remove dmach_t typedef
[safe/jmp/linux-2.6] / net / core / rtnetlink.c
index 61ac8d0..4dfb6b4 100644 (file)
@@ -73,7 +73,7 @@ void __rtnl_unlock(void)
 
 void rtnl_unlock(void)
 {
-       mutex_unlock(&rtnl_mutex);
+       /* This fellow will unlock it for us. */
        netdev_run_todo();
 }
 
@@ -82,6 +82,11 @@ int rtnl_trylock(void)
        return mutex_trylock(&rtnl_mutex);
 }
 
+int rtnl_is_locked(void)
+{
+       return mutex_is_locked(&rtnl_mutex);
+}
+
 static struct rtnl_link *rtnl_msg_handlers[NPROTO];
 
 static inline int rtm_msgindex(int msgtype)
@@ -269,6 +274,26 @@ int rtnl_link_register(struct rtnl_link_ops *ops)
 
 EXPORT_SYMBOL_GPL(rtnl_link_register);
 
+static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
+{
+       struct net_device *dev;
+restart:
+       for_each_netdev(net, dev) {
+               if (dev->rtnl_link_ops == ops) {
+                       ops->dellink(dev);
+                       goto restart;
+               }
+       }
+}
+
+void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
+{
+       rtnl_lock();
+       __rtnl_kill_links(net, ops);
+       rtnl_unlock();
+}
+EXPORT_SYMBOL_GPL(rtnl_kill_links);
+
 /**
  * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
  * @ops: struct rtnl_link_ops * to unregister
@@ -277,17 +302,10 @@ EXPORT_SYMBOL_GPL(rtnl_link_register);
  */
 void __rtnl_link_unregister(struct rtnl_link_ops *ops)
 {
-       struct net_device *dev, *n;
        struct net *net;
 
        for_each_net(net) {
-restart:
-               for_each_netdev_safe(net, dev, n) {
-                       if (dev->rtnl_link_ops == ops) {
-                               ops->dellink(dev);
-                               goto restart;
-                       }
-               }
+               __rtnl_kill_links(net, ops);
        }
        list_del(&ops->list);
 }
@@ -480,7 +498,8 @@ int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics)
        return nla_nest_end(skb, mx);
 
 nla_put_failure:
-       return nla_nest_cancel(skb, mx);
+       nla_nest_cancel(skb, mx);
+       return -EMSGSIZE;
 }
 
 int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
@@ -567,6 +586,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev)
 {
        return NLMSG_ALIGN(sizeof(struct ifinfomsg))
               + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+              + nla_total_size(IFALIASZ) /* IFLA_IFALIAS */
               + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */
               + nla_total_size(sizeof(struct rtnl_link_ifmap))
               + nla_total_size(sizeof(struct rtnl_link_stats))
@@ -586,8 +606,11 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                            int type, u32 pid, u32 seq, u32 change,
                            unsigned int flags)
 {
+       struct netdev_queue *txq;
        struct ifinfomsg *ifm;
        struct nlmsghdr *nlh;
+       struct net_device_stats *stats;
+       struct nlattr *attr;
 
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
        if (nlh == NULL)
@@ -614,8 +637,12 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
        if (dev->master)
                NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex);
 
-       if (dev->qdisc_sleeping)
-               NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc_sleeping->ops->id);
+       txq = netdev_get_tx_queue(dev, 0);
+       if (txq->qdisc_sleeping)
+               NLA_PUT_STRING(skb, IFLA_QDISC, txq->qdisc_sleeping->ops->id);
+
+       if (dev->ifalias)
+               NLA_PUT_STRING(skb, IFLA_IFALIAS, dev->ifalias);
 
        if (1) {
                struct rtnl_link_ifmap map = {
@@ -634,19 +661,13 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast);
        }
 
-       if (dev->get_stats) {
-               struct net_device_stats *stats = dev->get_stats(dev);
-               if (stats) {
-                       struct nlattr *attr;
-
-                       attr = nla_reserve(skb, IFLA_STATS,
-                                          sizeof(struct rtnl_link_stats));
-                       if (attr == NULL)
-                               goto nla_put_failure;
+       attr = nla_reserve(skb, IFLA_STATS,
+                       sizeof(struct rtnl_link_stats));
+       if (attr == NULL)
+               goto nla_put_failure;
 
-                       copy_rtnl_link_stats(nla_data(attr), stats);
-               }
-       }
+       stats = dev->get_stats(dev);
+       copy_rtnl_link_stats(nla_data(attr), stats);
 
        if (dev->rtnl_link_ops) {
                if (rtnl_link_fill(skb, dev) < 0)
@@ -662,7 +683,7 @@ nla_put_failure:
 
 static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       struct net *net = skb->sk->sk_net;
+       struct net *net = sock_net(skb->sk);
        int idx;
        int s_idx = cb->args[0];
        struct net_device *dev;
@@ -689,11 +710,14 @@ 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 },
+       [IFLA_IFALIAS]          = { .type = NLA_STRING, .len = IFALIASZ-1 },
 };
 
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -720,6 +744,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)
 {
@@ -819,6 +858,14 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
                modified = 1;
        }
 
+       if (tb[IFLA_IFALIAS]) {
+               err = dev_set_alias(dev, nla_data(tb[IFLA_IFALIAS]),
+                                   nla_len(tb[IFLA_IFALIAS]));
+               if (err < 0)
+                       goto errout;
+               modified = 1;
+       }
+
        if (tb[IFLA_BROADCAST]) {
                nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
                send_addr_notify = 1;
@@ -831,7 +878,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
                if (ifm->ifi_change)
                        flags = (flags & ifm->ifi_change) |
                                (dev->flags & ~ifm->ifi_change);
-               dev_change_flags(dev, flags);
+               err = dev_change_flags(dev, flags);
+               if (err < 0)
+                       goto errout;
        }
 
        if (tb[IFLA_TXQLEN])
@@ -862,7 +911,7 @@ errout:
 
 static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
-       struct net *net = skb->sk->sk_net;
+       struct net *net = sock_net(skb->sk);
        struct ifinfomsg *ifm;
        struct net_device *dev;
        int err;
@@ -892,12 +941,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);
@@ -909,7 +953,7 @@ errout:
 
 static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
-       struct net *net = skb->sk->sk_net;
+       struct net *net = sock_net(skb->sk);
        const struct rtnl_link_ops *ops;
        struct net_device *dev;
        struct ifinfomsg *ifm;
@@ -960,7 +1004,7 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
                        goto err_free;
        }
 
-       dev->nd_net = net;
+       dev_net_set(dev, net);
        dev->rtnl_link_ops = ops;
 
        if (tb[IFLA_MTU])
@@ -988,7 +1032,7 @@ err:
 
 static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
-       struct net *net = skb->sk->sk_net;
+       struct net *net = sock_net(skb->sk);
        const struct rtnl_link_ops *ops;
        struct net_device *dev;
        struct ifinfomsg *ifm;
@@ -998,7 +1042,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        struct nlattr *linkinfo[IFLA_INFO_MAX+1];
        int err;
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 replay:
 #endif
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
@@ -1018,6 +1062,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);
@@ -1084,7 +1131,7 @@ replay:
                        return -EOPNOTSUPP;
 
                if (!ops) {
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
                        if (kind[0]) {
                                __rtnl_unlock();
                                request_module("rtnl-link-%s", kind);
@@ -1117,7 +1164,7 @@ replay:
 
 static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
-       struct net *net = skb->sk->sk_net;
+       struct net *net = sock_net(skb->sk);
        struct ifinfomsg *ifm;
        struct nlattr *tb[IFLA_MAX+1];
        struct net_device *dev = NULL;
@@ -1183,7 +1230,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
 
 void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
 {
-       struct net *net = dev->nd_net;
+       struct net *net = dev_net(dev);
        struct sk_buff *skb;
        int err = -ENOBUFS;
 
@@ -1212,7 +1259,7 @@ static int rtattr_max;
 
 static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
-       struct net *net = skb->sk->sk_net;
+       struct net *net = sock_net(skb->sk);
        rtnl_doit_func doit;
        int sz_idx, kind;
        int min_len;
@@ -1374,6 +1421,7 @@ EXPORT_SYMBOL(rtnetlink_put_metrics);
 EXPORT_SYMBOL(rtnl_lock);
 EXPORT_SYMBOL(rtnl_trylock);
 EXPORT_SYMBOL(rtnl_unlock);
+EXPORT_SYMBOL(rtnl_is_locked);
 EXPORT_SYMBOL(rtnl_unicast);
 EXPORT_SYMBOL(rtnl_notify);
 EXPORT_SYMBOL(rtnl_set_sk_err);