#include <linux/types.h>
 #include <linux/skbuff.h>
 #include <linux/net.h>
+#include <linux/netdevice.h>
 #include <linux/if.h>
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/wait.h>
 #include <linux/list.h>
+#include <net/net_namespace.h>
 #endif
 #include <linux/compiler.h>
 
 #define NF_MAX_HOOKS 8
 
 struct sk_buff;
-struct net_device;
 
 typedef unsigned int nf_hookfn(unsigned int hooknum,
                               struct sk_buff *skb,
 static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
 #endif
 
+static inline struct net *nf_pre_routing_net(const struct net_device *in,
+                                            const struct net_device *out)
+{
+#ifdef CONFIG_NET_NS
+       return in->nd_net;
+#else
+       return &init_net;
+#endif
+}
+
+static inline struct net *nf_local_in_net(const struct net_device *in,
+                                         const struct net_device *out)
+{
+#ifdef CONFIG_NET_NS
+       return in->nd_net;
+#else
+       return &init_net;
+#endif
+}
+
+static inline struct net *nf_forward_net(const struct net_device *in,
+                                        const struct net_device *out)
+{
+#ifdef CONFIG_NET_NS
+       BUG_ON(in->nd_net != out->nd_net);
+       return in->nd_net;
+#else
+       return &init_net;
+#endif
+}
+
+static inline struct net *nf_local_out_net(const struct net_device *in,
+                                          const struct net_device *out)
+{
+#ifdef CONFIG_NET_NS
+       return out->nd_net;
+#else
+       return &init_net;
+#endif
+}
+
+static inline struct net *nf_post_routing_net(const struct net_device *in,
+                                             const struct net_device *out)
+{
+#ifdef CONFIG_NET_NS
+       return out->nd_net;
+#else
+       return &init_net;
+#endif
+}
+
 #endif /*__KERNEL__*/
 #endif /*__LINUX_NETFILTER_H*/
 
 };
 
 /* The work comes in here from netfilter.c. */
+static unsigned int
+ipt_local_in_hook(unsigned int hook,
+                 struct sk_buff *skb,
+                 const struct net_device *in,
+                 const struct net_device *out,
+                 int (*okfn)(struct sk_buff *))
+{
+       return ipt_do_table(skb, hook, in, out,
+                           nf_local_in_net(in, out)->ipv4.iptable_filter);
+}
+
 static unsigned int
 ipt_hook(unsigned int hook,
         struct sk_buff *skb,
         const struct net_device *out,
         int (*okfn)(struct sk_buff *))
 {
-       return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter);
+       return ipt_do_table(skb, hook, in, out,
+                           nf_forward_net(in, out)->ipv4.iptable_filter);
 }
 
 static unsigned int
                return NF_ACCEPT;
        }
 
-       return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter);
+       return ipt_do_table(skb, hook, in, out,
+                           nf_local_out_net(in, out)->ipv4.iptable_filter);
 }
 
 static struct nf_hook_ops ipt_ops[] __read_mostly = {
        {
-               .hook           = ipt_hook,
+               .hook           = ipt_local_in_hook,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
                .hooknum        = NF_INET_LOCAL_IN,
 
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
-ipt_route_hook(unsigned int hook,
+ipt_pre_routing_hook(unsigned int hook,
+                    struct sk_buff *skb,
+                    const struct net_device *in,
+                    const struct net_device *out,
+                    int (*okfn)(struct sk_buff *))
+{
+       return ipt_do_table(skb, hook, in, out,
+                           nf_pre_routing_net(in, out)->ipv4.iptable_mangle);
+}
+
+static unsigned int
+ipt_post_routing_hook(unsigned int hook,
+                     struct sk_buff *skb,
+                     const struct net_device *in,
+                     const struct net_device *out,
+                     int (*okfn)(struct sk_buff *))
+{
+       return ipt_do_table(skb, hook, in, out,
+                           nf_post_routing_net(in, out)->ipv4.iptable_mangle);
+}
+
+static unsigned int
+ipt_local_in_hook(unsigned int hook,
+                 struct sk_buff *skb,
+                 const struct net_device *in,
+                 const struct net_device *out,
+                 int (*okfn)(struct sk_buff *))
+{
+       return ipt_do_table(skb, hook, in, out,
+                           nf_local_in_net(in, out)->ipv4.iptable_mangle);
+}
+
+static unsigned int
+ipt_forward_hook(unsigned int hook,
         struct sk_buff *skb,
         const struct net_device *in,
         const struct net_device *out,
         int (*okfn)(struct sk_buff *))
 {
-       return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle);
+       return ipt_do_table(skb, hook, in, out,
+                           nf_forward_net(in, out)->ipv4.iptable_mangle);
 }
 
 static unsigned int
        daddr = iph->daddr;
        tos = iph->tos;
 
-       ret = ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle);
+       ret = ipt_do_table(skb, hook, in, out,
+                          nf_local_out_net(in, out)->ipv4.iptable_mangle);
        /* Reroute for ANY change. */
        if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
                iph = ip_hdr(skb);
 
 static struct nf_hook_ops ipt_ops[] __read_mostly = {
        {
-               .hook           = ipt_route_hook,
+               .hook           = ipt_pre_routing_hook,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
                .hooknum        = NF_INET_PRE_ROUTING,
                .priority       = NF_IP_PRI_MANGLE,
        },
        {
-               .hook           = ipt_route_hook,
+               .hook           = ipt_local_in_hook,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
                .hooknum        = NF_INET_LOCAL_IN,
                .priority       = NF_IP_PRI_MANGLE,
        },
        {
-               .hook           = ipt_route_hook,
+               .hook           = ipt_forward_hook,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
                .hooknum        = NF_INET_FORWARD,
                .priority       = NF_IP_PRI_MANGLE,
        },
        {
-               .hook           = ipt_route_hook,
+               .hook           = ipt_post_routing_hook,
                .owner          = THIS_MODULE,
                .pf             = PF_INET,
                .hooknum        = NF_INET_POST_ROUTING,
 
         const struct net_device *out,
         int (*okfn)(struct sk_buff *))
 {
-       return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw);
+       return ipt_do_table(skb, hook, in, out,
+                           nf_pre_routing_net(in, out)->ipv4.iptable_raw);
 }
 
 static unsigned int
                               "packet.\n");
                return NF_ACCEPT;
        }
-       return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw);
+       return ipt_do_table(skb, hook, in, out,
+                           nf_local_out_net(in, out)->ipv4.iptable_raw);
 }
 
 /* 'raw' is the very first table. */