({     data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
        __rtattr_parse_nested_compat(tb, max, rta, len); })
 
-extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
-extern int rtnl_unicast(struct sk_buff *skb, u32 pid);
-extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
+extern int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, u32 group, int echo);
+extern int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid);
+extern int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
                       struct nlmsghdr *nlh, gfp_t flags);
-extern void rtnl_set_sk_err(u32 group, int error);
+extern void rtnl_set_sk_err(struct net *net, u32 group, int error);
 extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics);
 extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst,
                              u32 id, u32 ts, u32 tsage, long expires,
 
 
 struct proc_dir_entry;
 struct net_device;
+struct sock;
 struct net {
        atomic_t                count;          /* To decided when the network
                                                 *  namespace should be freed.
        struct list_head        dev_base_head;
        struct hlist_head       *dev_name_head;
        struct hlist_head       *dev_index_head;
+
+       struct sock             *rtnl;                  /* rtnetlink socket */
 };
 
 #ifdef CONFIG_NET
 
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
+       err = rtnl_notify(skb, &init_net,0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_LINK, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_LINK, err);
 }
 
 /*
 
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
+       err = rtnl_notify(skb, &init_net, pid, ops->nlgroup, nlh, GFP_KERNEL);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(ops->nlgroup, err);
+               rtnl_set_sk_err(&init_net, ops->nlgroup, err);
 }
 
 static void attach_rules(struct list_head *rules, struct net_device *dev)
 
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
+       err = rtnl_notify(skb, &init_net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_NEIGH, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_NEIGH, err);
 }
 
 #ifdef CONFIG_ARPD
 
 };
 
 static DEFINE_MUTEX(rtnl_mutex);
-static struct sock *rtnl;
 
 void rtnl_lock(void)
 {
        return ret;
 }
 
-int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
+int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo)
 {
+       struct sock *rtnl = net->rtnl;
        int err = 0;
 
        NETLINK_CB(skb).dst_group = group;
        return err;
 }
 
-int rtnl_unicast(struct sk_buff *skb, u32 pid)
+int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid)
 {
+       struct sock *rtnl = net->rtnl;
+
        return nlmsg_unicast(rtnl, skb, pid);
 }
 
-int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
+int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
                struct nlmsghdr *nlh, gfp_t flags)
 {
+       struct sock *rtnl = net->rtnl;
        int report = 0;
 
        if (nlh)
        return nlmsg_notify(rtnl, skb, pid, group, report, flags);
 }
 
-void rtnl_set_sk_err(u32 group, int error)
+void rtnl_set_sk_err(struct net *net, u32 group, int error)
 {
+       struct sock *rtnl = net->rtnl;
+
        netlink_set_err(rtnl, 0, group, error);
 }
 
                kfree_skb(nskb);
                goto errout;
        }
-       err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
+       err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid);
 errout:
        dev_put(dev);
 
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+       err = rtnl_notify(skb, &init_net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_LINK, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_LINK, err);
 }
 
 /* Protected by RTNL sempahore.  */
 
 static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
+       struct net *net = skb->sk->sk_net;
        rtnl_doit_func doit;
        int sz_idx, kind;
        int min_len;
                return -EPERM;
 
        if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
+               struct sock *rtnl;
                rtnl_dumpit_func dumpit;
 
                dumpit = rtnl_get_dumpit(family, type);
                        return -EOPNOTSUPP;
 
                __rtnl_unlock();
+               rtnl = net->rtnl;
                err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
                rtnl_lock();
                return err;
        .notifier_call  = rtnetlink_event,
 };
 
+
+static int rtnetlink_net_init(struct net *net)
+{
+       struct sock *sk;
+       sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX,
+                                  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);
+               sock_put(sk);
+               net->rtnl = NULL;
+       }
+}
+
+static struct pernet_operations rtnetlink_net_ops = {
+       .init = rtnetlink_net_init,
+       .exit = rtnetlink_net_exit,
+};
+
 void __init rtnetlink_init(void)
 {
        int i;
        if (!rta_buf)
                panic("rtnetlink_init: cannot allocate rta_buf\n");
 
-       rtnl = netlink_kernel_create(&init_net, NETLINK_ROUTE, RTNLGRP_MAX,
-                                    rtnetlink_rcv, &rtnl_mutex, THIS_MODULE);
-       if (rtnl == NULL)
+       if (register_pernet_subsys(&rtnetlink_net_ops))
                panic("rtnetlink_init: cannot initialize rtnetlink\n");
+
        netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
        register_netdevice_notifier(&rtnetlink_dev_notifier);
 
 
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
+       err = rtnl_notify(skb, &init_net, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_IFADDR, err);
 }
 
 static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 
                goto out_free;
        }
 
-       return rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+       return rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
 
 out_free:
        kfree_skb(skb);
 
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
+       err = rtnl_notify(skb, &init_net, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_DECnet_ROUTE, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_ROUTE, err);
 }
 
 static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
 
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
+       err = rtnl_notify(skb, &init_net, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_IPV4_IFADDR, err);
 }
 
 #ifdef CONFIG_SYSCTL
 
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
+       err = rtnl_notify(skb, &init_net, info->pid, RTNLGRP_IPV4_ROUTE,
                          info->nlh, GFP_KERNEL);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_IPV4_ROUTE, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_IPV4_ROUTE, err);
 }
 
 /* Return the first fib alias matching TOS with
 
                        e->error = -ETIMEDOUT;
                        memset(&e->msg, 0, sizeof(e->msg));
 
-                       rtnl_unicast(skb, NETLINK_CB(skb).pid);
+                       rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
                } else
                        kfree_skb(skb);
        }
                                memset(&e->msg, 0, sizeof(e->msg));
                        }
 
-                       rtnl_unicast(skb, NETLINK_CB(skb).pid);
+                       rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
                } else
                        ip_mr_forward(skb, c, 0);
        }
 
        if (err <= 0)
                goto errout_free;
 
-       err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+       err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
 errout:
        return err;
 
 
                kfree_skb(skb);
                goto errout_ifa;
        }
-       err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+       err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
 errout_ifa:
        in6_ifa_put(ifa);
 errout:
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+       err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
 }
 
 static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+       err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
 }
 
 static inline size_t inet6_prefix_nlmsg_size(void)
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
+       err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_PREFIX, err);
 }
 
 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
                goto out;
        }
 
-       err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+       err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
 out:
        return err;
 }
 
                &ipv6_hdr(ra)->saddr);
        nlmsg_end(skb, nlh);
 
-       err = rtnl_notify(skb, 0, RTNLGRP_ND_USEROPT, NULL, GFP_ATOMIC);
+       err = rtnl_notify(skb, &init_net, 0, RTNLGRP_ND_USEROPT, NULL,
+                         GFP_ATOMIC);
        if (err < 0)
                goto errout;
 
        nlmsg_free(skb);
        err = -EMSGSIZE;
 errout:
-       rtnl_set_sk_err(RTNLGRP_ND_USEROPT, err);
+       rtnl_set_sk_err(&init_net, RTNLGRP_ND_USEROPT, err);
 }
 
 static void ndisc_router_discovery(struct sk_buff *skb)
 
                goto errout;
        }
 
-       err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+       err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
 errout:
        return err;
 }
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
+       err = rtnl_notify(skb, &init_net, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_IPV6_ROUTE, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err);
 }
 
 /*
 
                return -EINVAL;
        }
 
-       return rtnl_unicast(skb, pid);
+       return rtnl_unicast(skb, &init_net, pid);
 }
 
 static struct tc_action *
        nlh->nlmsg_flags |= NLM_F_ROOT;
        module_put(a->ops->owner);
        kfree(a);
-       err = rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+       err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
        if (err > 0)
                return 0;
 
 
                /* now do the delete */
                tcf_action_destroy(head, 0);
-               ret = rtnetlink_send(skb, pid, RTNLGRP_TC,
+               ret = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC,
                                     n->nlmsg_flags&NLM_F_ECHO);
                if (ret > 0)
                        return 0;
        nlh->nlmsg_len = skb_tail_pointer(skb) - b;
        NETLINK_CB(skb).dst_group = RTNLGRP_TC;
 
-       err = rtnetlink_send(skb, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
+       err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
        if (err > 0)
                err = 0;
        return err;
 
                return -EINVAL;
        }
 
-       return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+       return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
 }
 
 struct tcf_dump_args
 
        }
 
        if (skb->len)
-               return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+               return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
 
 err_out:
        kfree_skb(skb);
                return -EINVAL;
        }
 
-       return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+       return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
 }
 
 struct qdisc_dump_args
 
        struct sk_buff *skb;
 
        while ((skb = skb_dequeue(&wireless_nlevent_queue)))
-               rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
+               rtnl_notify(skb, &init_net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
 }
 
 static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
        struct sk_buff *skb;
        int err;
 
+       if (dev->nd_net != &init_net)
+               return;
+
        skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
        if (!skb)
                return;