]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - net/ipv4/netfilter/iptable_nat.c
Merge branch 'work.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[mirror_ubuntu-bionic-kernel.git] / net / ipv4 / netfilter / iptable_nat.c
CommitLineData
5b1158e9
JK
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
c7232c99 3 * (C) 2011 Patrick McHardy <kaber@trash.net>
5b1158e9
JK
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
c7232c99
PM
9
10#include <linux/module.h>
5b1158e9
JK
11#include <linux/netfilter.h>
12#include <linux/netfilter_ipv4.h>
c7232c99
PM
13#include <linux/netfilter_ipv4/ip_tables.h>
14#include <linux/ip.h>
5b1158e9 15#include <net/ip.h>
5b1158e9 16
5b1158e9 17#include <net/netfilter/nf_nat.h>
5b1158e9 18#include <net/netfilter/nf_nat_core.h>
c7232c99
PM
19#include <net/netfilter/nf_nat_l3proto.h>
20
b9e69e12
FW
21static int __net_init iptable_nat_table_init(struct net *net);
22
c7232c99
PM
23static const struct xt_table nf_nat_ipv4_table = {
24 .name = "nat",
25 .valid_hooks = (1 << NF_INET_PRE_ROUTING) |
26 (1 << NF_INET_POST_ROUTING) |
27 (1 << NF_INET_LOCAL_OUT) |
28 (1 << NF_INET_LOCAL_IN),
29 .me = THIS_MODULE,
30 .af = NFPROTO_IPV4,
b9e69e12 31 .table_init = iptable_nat_table_init,
c7232c99 32};
5b1158e9 33
06198b34 34static unsigned int iptable_nat_do_chain(void *priv,
30766f4c 35 struct sk_buff *skb,
d7cf4081 36 const struct nf_hook_state *state,
30766f4c 37 struct nf_conn *ct)
c7232c99 38{
6cb8ff3f 39 return ipt_do_table(skb, state, state->net->ipv4.nat_table);
5b1158e9 40}
5b1158e9 41
06198b34 42static unsigned int iptable_nat_ipv4_fn(void *priv,
30766f4c 43 struct sk_buff *skb,
238e54c9 44 const struct nf_hook_state *state)
5b1158e9 45{
06198b34 46 return nf_nat_ipv4_fn(priv, skb, state, iptable_nat_do_chain);
5b1158e9
JK
47}
48
06198b34 49static unsigned int iptable_nat_ipv4_in(void *priv,
30766f4c 50 struct sk_buff *skb,
238e54c9 51 const struct nf_hook_state *state)
5b1158e9 52{
06198b34 53 return nf_nat_ipv4_in(priv, skb, state, iptable_nat_do_chain);
5b1158e9
JK
54}
55
06198b34 56static unsigned int iptable_nat_ipv4_out(void *priv,
30766f4c 57 struct sk_buff *skb,
238e54c9 58 const struct nf_hook_state *state)
5b1158e9 59{
06198b34 60 return nf_nat_ipv4_out(priv, skb, state, iptable_nat_do_chain);
5b1158e9
JK
61}
62
06198b34 63static unsigned int iptable_nat_ipv4_local_fn(void *priv,
30766f4c 64 struct sk_buff *skb,
238e54c9 65 const struct nf_hook_state *state)
5b1158e9 66{
06198b34 67 return nf_nat_ipv4_local_fn(priv, skb, state, iptable_nat_do_chain);
5b1158e9
JK
68}
69
c7232c99 70static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
5b1158e9
JK
71 /* Before packet filtering, change destination */
72 {
30766f4c 73 .hook = iptable_nat_ipv4_in,
24c232d8 74 .pf = NFPROTO_IPV4,
6e23ae2a 75 .hooknum = NF_INET_PRE_ROUTING,
5b1158e9
JK
76 .priority = NF_IP_PRI_NAT_DST,
77 },
78 /* After packet filtering, change source */
79 {
30766f4c 80 .hook = iptable_nat_ipv4_out,
24c232d8 81 .pf = NFPROTO_IPV4,
6e23ae2a 82 .hooknum = NF_INET_POST_ROUTING,
5b1158e9
JK
83 .priority = NF_IP_PRI_NAT_SRC,
84 },
5b1158e9
JK
85 /* Before packet filtering, change destination */
86 {
30766f4c 87 .hook = iptable_nat_ipv4_local_fn,
24c232d8 88 .pf = NFPROTO_IPV4,
6e23ae2a 89 .hooknum = NF_INET_LOCAL_OUT,
5b1158e9
JK
90 .priority = NF_IP_PRI_NAT_DST,
91 },
92 /* After packet filtering, change source */
93 {
30766f4c 94 .hook = iptable_nat_ipv4_fn,
24c232d8 95 .pf = NFPROTO_IPV4,
6e23ae2a 96 .hooknum = NF_INET_LOCAL_IN,
5b1158e9
JK
97 .priority = NF_IP_PRI_NAT_SRC,
98 },
5b1158e9
JK
99};
100
b9e69e12 101static int __net_init iptable_nat_table_init(struct net *net)
5b1158e9 102{
c7232c99 103 struct ipt_replace *repl;
a67dd266 104 int ret;
c7232c99 105
b9e69e12
FW
106 if (net->ipv4.nat_table)
107 return 0;
108
c7232c99
PM
109 repl = ipt_alloc_initial_table(&nf_nat_ipv4_table);
110 if (repl == NULL)
111 return -ENOMEM;
a67dd266
FW
112 ret = ipt_register_table(net, &nf_nat_ipv4_table, repl,
113 nf_nat_ipv4_ops, &net->ipv4.nat_table);
c7232c99 114 kfree(repl);
a67dd266 115 return ret;
c7232c99 116}
5b1158e9 117
c7232c99
PM
118static void __net_exit iptable_nat_net_exit(struct net *net)
119{
b9e69e12
FW
120 if (!net->ipv4.nat_table)
121 return;
a67dd266 122 ipt_unregister_table(net, net->ipv4.nat_table, nf_nat_ipv4_ops);
b9e69e12 123 net->ipv4.nat_table = NULL;
c7232c99 124}
5b1158e9 125
c7232c99 126static struct pernet_operations iptable_nat_net_ops = {
c7232c99
PM
127 .exit = iptable_nat_net_exit,
128};
5b1158e9 129
c7232c99
PM
130static int __init iptable_nat_init(void)
131{
b9e69e12 132 int ret = register_pernet_subsys(&iptable_nat_net_ops);
c7232c99 133
b9e69e12
FW
134 if (ret)
135 return ret;
c7232c99 136
b9e69e12
FW
137 ret = iptable_nat_table_init(&init_net);
138 if (ret)
139 unregister_pernet_subsys(&iptable_nat_net_ops);
140 return ret;
5b1158e9
JK
141}
142
c7232c99 143static void __exit iptable_nat_exit(void)
5b1158e9 144{
c7232c99 145 unregister_pernet_subsys(&iptable_nat_net_ops);
5b1158e9
JK
146}
147
c7232c99
PM
148module_init(iptable_nat_init);
149module_exit(iptable_nat_exit);
5b1158e9
JK
150
151MODULE_LICENSE("GPL");