Commit | Line | Data |
---|---|---|
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 |
21 | static int __net_init iptable_nat_table_init(struct net *net); |
22 | ||
c7232c99 PM |
23 | static 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 | 34 | static 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 | 42 | static 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 | 49 | static 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 | 56 | static 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 | 63 | static 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 | 70 | static 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 | 101 | static 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 |
118 | static 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 | 126 | static struct pernet_operations iptable_nat_net_ops = { |
c7232c99 PM |
127 | .exit = iptable_nat_net_exit, |
128 | }; | |
5b1158e9 | 129 | |
c7232c99 PM |
130 | static 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 | 143 | static void __exit iptable_nat_exit(void) |
5b1158e9 | 144 | { |
c7232c99 | 145 | unregister_pernet_subsys(&iptable_nat_net_ops); |
5b1158e9 JK |
146 | } |
147 | ||
c7232c99 PM |
148 | module_init(iptable_nat_init); |
149 | module_exit(iptable_nat_exit); | |
5b1158e9 JK |
150 | |
151 | MODULE_LICENSE("GPL"); |