Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / net / ipv4 / netfilter / iptable_nat.c
diff --git a/kernel/net/ipv4/netfilter/iptable_nat.c b/kernel/net/ipv4/netfilter/iptable_nat.c
new file mode 100644 (file)
index 0000000..0d4d9cd
--- /dev/null
@@ -0,0 +1,154 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_nat_l3proto.h>
+
+static const struct xt_table nf_nat_ipv4_table = {
+       .name           = "nat",
+       .valid_hooks    = (1 << NF_INET_PRE_ROUTING) |
+                         (1 << NF_INET_POST_ROUTING) |
+                         (1 << NF_INET_LOCAL_OUT) |
+                         (1 << NF_INET_LOCAL_IN),
+       .me             = THIS_MODULE,
+       .af             = NFPROTO_IPV4,
+};
+
+static unsigned int iptable_nat_do_chain(const struct nf_hook_ops *ops,
+                                        struct sk_buff *skb,
+                                        const struct nf_hook_state *state,
+                                        struct nf_conn *ct)
+{
+       struct net *net = nf_ct_net(ct);
+
+       return ipt_do_table(skb, ops->hooknum, state, net->ipv4.nat_table);
+}
+
+static unsigned int iptable_nat_ipv4_fn(const struct nf_hook_ops *ops,
+                                       struct sk_buff *skb,
+                                       const struct nf_hook_state *state)
+{
+       return nf_nat_ipv4_fn(ops, skb, state, iptable_nat_do_chain);
+}
+
+static unsigned int iptable_nat_ipv4_in(const struct nf_hook_ops *ops,
+                                       struct sk_buff *skb,
+                                       const struct nf_hook_state *state)
+{
+       return nf_nat_ipv4_in(ops, skb, state, iptable_nat_do_chain);
+}
+
+static unsigned int iptable_nat_ipv4_out(const struct nf_hook_ops *ops,
+                                        struct sk_buff *skb,
+                                        const struct nf_hook_state *state)
+{
+       return nf_nat_ipv4_out(ops, skb, state, iptable_nat_do_chain);
+}
+
+static unsigned int iptable_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
+                                             struct sk_buff *skb,
+                                             const struct nf_hook_state *state)
+{
+       return nf_nat_ipv4_local_fn(ops, skb, state, iptable_nat_do_chain);
+}
+
+static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
+       /* Before packet filtering, change destination */
+       {
+               .hook           = iptable_nat_ipv4_in,
+               .owner          = THIS_MODULE,
+               .pf             = NFPROTO_IPV4,
+               .hooknum        = NF_INET_PRE_ROUTING,
+               .priority       = NF_IP_PRI_NAT_DST,
+       },
+       /* After packet filtering, change source */
+       {
+               .hook           = iptable_nat_ipv4_out,
+               .owner          = THIS_MODULE,
+               .pf             = NFPROTO_IPV4,
+               .hooknum        = NF_INET_POST_ROUTING,
+               .priority       = NF_IP_PRI_NAT_SRC,
+       },
+       /* Before packet filtering, change destination */
+       {
+               .hook           = iptable_nat_ipv4_local_fn,
+               .owner          = THIS_MODULE,
+               .pf             = NFPROTO_IPV4,
+               .hooknum        = NF_INET_LOCAL_OUT,
+               .priority       = NF_IP_PRI_NAT_DST,
+       },
+       /* After packet filtering, change source */
+       {
+               .hook           = iptable_nat_ipv4_fn,
+               .owner          = THIS_MODULE,
+               .pf             = NFPROTO_IPV4,
+               .hooknum        = NF_INET_LOCAL_IN,
+               .priority       = NF_IP_PRI_NAT_SRC,
+       },
+};
+
+static int __net_init iptable_nat_net_init(struct net *net)
+{
+       struct ipt_replace *repl;
+
+       repl = ipt_alloc_initial_table(&nf_nat_ipv4_table);
+       if (repl == NULL)
+               return -ENOMEM;
+       net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
+       kfree(repl);
+       return PTR_ERR_OR_ZERO(net->ipv4.nat_table);
+}
+
+static void __net_exit iptable_nat_net_exit(struct net *net)
+{
+       ipt_unregister_table(net, net->ipv4.nat_table);
+}
+
+static struct pernet_operations iptable_nat_net_ops = {
+       .init   = iptable_nat_net_init,
+       .exit   = iptable_nat_net_exit,
+};
+
+static int __init iptable_nat_init(void)
+{
+       int err;
+
+       err = register_pernet_subsys(&iptable_nat_net_ops);
+       if (err < 0)
+               goto err1;
+
+       err = nf_register_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
+       if (err < 0)
+               goto err2;
+       return 0;
+
+err2:
+       unregister_pernet_subsys(&iptable_nat_net_ops);
+err1:
+       return err;
+}
+
+static void __exit iptable_nat_exit(void)
+{
+       nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
+       unregister_pernet_subsys(&iptable_nat_net_ops);
+}
+
+module_init(iptable_nat_init);
+module_exit(iptable_nat_exit);
+
+MODULE_LICENSE("GPL");