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 | ||
21 | static const struct xt_table nf_nat_ipv4_table = { | |
22 | .name = "nat", | |
23 | .valid_hooks = (1 << NF_INET_PRE_ROUTING) | | |
24 | (1 << NF_INET_POST_ROUTING) | | |
25 | (1 << NF_INET_LOCAL_OUT) | | |
26 | (1 << NF_INET_LOCAL_IN), | |
27 | .me = THIS_MODULE, | |
28 | .af = NFPROTO_IPV4, | |
29 | }; | |
5b1158e9 | 30 | |
30766f4c PNA |
31 | static unsigned int iptable_nat_do_chain(const struct nf_hook_ops *ops, |
32 | struct sk_buff *skb, | |
33 | const struct net_device *in, | |
34 | const struct net_device *out, | |
35 | struct nf_conn *ct) | |
c7232c99 PM |
36 | { |
37 | struct net *net = nf_ct_net(ct); | |
5b1158e9 | 38 | |
30766f4c | 39 | return ipt_do_table(skb, ops->hooknum, in, out, net->ipv4.nat_table); |
5b1158e9 | 40 | } |
5b1158e9 | 41 | |
30766f4c PNA |
42 | static unsigned int iptable_nat_ipv4_fn(const struct nf_hook_ops *ops, |
43 | struct sk_buff *skb, | |
44 | const struct net_device *in, | |
45 | const struct net_device *out, | |
46 | int (*okfn)(struct sk_buff *)) | |
5b1158e9 | 47 | { |
30766f4c | 48 | return nf_nat_ipv4_fn(ops, skb, in, out, iptable_nat_do_chain); |
5b1158e9 JK |
49 | } |
50 | ||
30766f4c PNA |
51 | static unsigned int iptable_nat_ipv4_in(const struct nf_hook_ops *ops, |
52 | struct sk_buff *skb, | |
53 | const struct net_device *in, | |
54 | const struct net_device *out, | |
55 | int (*okfn)(struct sk_buff *)) | |
5b1158e9 | 56 | { |
30766f4c | 57 | return nf_nat_ipv4_in(ops, skb, in, out, iptable_nat_do_chain); |
5b1158e9 JK |
58 | } |
59 | ||
30766f4c PNA |
60 | static unsigned int iptable_nat_ipv4_out(const struct nf_hook_ops *ops, |
61 | struct sk_buff *skb, | |
62 | const struct net_device *in, | |
63 | const struct net_device *out, | |
64 | int (*okfn)(struct sk_buff *)) | |
5b1158e9 | 65 | { |
30766f4c | 66 | return nf_nat_ipv4_out(ops, skb, in, out, iptable_nat_do_chain); |
5b1158e9 JK |
67 | } |
68 | ||
30766f4c PNA |
69 | static unsigned int iptable_nat_ipv4_local_fn(const struct nf_hook_ops *ops, |
70 | struct sk_buff *skb, | |
71 | const struct net_device *in, | |
72 | const struct net_device *out, | |
73 | int (*okfn)(struct sk_buff *)) | |
5b1158e9 | 74 | { |
30766f4c | 75 | return nf_nat_ipv4_local_fn(ops, skb, in, out, iptable_nat_do_chain); |
5b1158e9 JK |
76 | } |
77 | ||
c7232c99 | 78 | static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = { |
5b1158e9 JK |
79 | /* Before packet filtering, change destination */ |
80 | { | |
30766f4c | 81 | .hook = iptable_nat_ipv4_in, |
5b1158e9 | 82 | .owner = THIS_MODULE, |
24c232d8 | 83 | .pf = NFPROTO_IPV4, |
6e23ae2a | 84 | .hooknum = NF_INET_PRE_ROUTING, |
5b1158e9 JK |
85 | .priority = NF_IP_PRI_NAT_DST, |
86 | }, | |
87 | /* After packet filtering, change source */ | |
88 | { | |
30766f4c | 89 | .hook = iptable_nat_ipv4_out, |
5b1158e9 | 90 | .owner = THIS_MODULE, |
24c232d8 | 91 | .pf = NFPROTO_IPV4, |
6e23ae2a | 92 | .hooknum = NF_INET_POST_ROUTING, |
5b1158e9 JK |
93 | .priority = NF_IP_PRI_NAT_SRC, |
94 | }, | |
5b1158e9 JK |
95 | /* Before packet filtering, change destination */ |
96 | { | |
30766f4c | 97 | .hook = iptable_nat_ipv4_local_fn, |
5b1158e9 | 98 | .owner = THIS_MODULE, |
24c232d8 | 99 | .pf = NFPROTO_IPV4, |
6e23ae2a | 100 | .hooknum = NF_INET_LOCAL_OUT, |
5b1158e9 JK |
101 | .priority = NF_IP_PRI_NAT_DST, |
102 | }, | |
103 | /* After packet filtering, change source */ | |
104 | { | |
30766f4c | 105 | .hook = iptable_nat_ipv4_fn, |
5b1158e9 | 106 | .owner = THIS_MODULE, |
24c232d8 | 107 | .pf = NFPROTO_IPV4, |
6e23ae2a | 108 | .hooknum = NF_INET_LOCAL_IN, |
5b1158e9 JK |
109 | .priority = NF_IP_PRI_NAT_SRC, |
110 | }, | |
5b1158e9 JK |
111 | }; |
112 | ||
c7232c99 | 113 | static int __net_init iptable_nat_net_init(struct net *net) |
5b1158e9 | 114 | { |
c7232c99 PM |
115 | struct ipt_replace *repl; |
116 | ||
117 | repl = ipt_alloc_initial_table(&nf_nat_ipv4_table); | |
118 | if (repl == NULL) | |
119 | return -ENOMEM; | |
120 | net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl); | |
121 | kfree(repl); | |
8c6ffba0 | 122 | return PTR_ERR_OR_ZERO(net->ipv4.nat_table); |
c7232c99 | 123 | } |
5b1158e9 | 124 | |
c7232c99 PM |
125 | static void __net_exit iptable_nat_net_exit(struct net *net) |
126 | { | |
127 | ipt_unregister_table(net, net->ipv4.nat_table); | |
128 | } | |
5b1158e9 | 129 | |
c7232c99 PM |
130 | static struct pernet_operations iptable_nat_net_ops = { |
131 | .init = iptable_nat_net_init, | |
132 | .exit = iptable_nat_net_exit, | |
133 | }; | |
5b1158e9 | 134 | |
c7232c99 PM |
135 | static int __init iptable_nat_init(void) |
136 | { | |
137 | int err; | |
138 | ||
139 | err = register_pernet_subsys(&iptable_nat_net_ops); | |
140 | if (err < 0) | |
141 | goto err1; | |
142 | ||
143 | err = nf_register_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops)); | |
144 | if (err < 0) | |
145 | goto err2; | |
146 | return 0; | |
147 | ||
148 | err2: | |
149 | unregister_pernet_subsys(&iptable_nat_net_ops); | |
150 | err1: | |
151 | return err; | |
5b1158e9 JK |
152 | } |
153 | ||
c7232c99 | 154 | static void __exit iptable_nat_exit(void) |
5b1158e9 | 155 | { |
c7232c99 PM |
156 | nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops)); |
157 | unregister_pernet_subsys(&iptable_nat_net_ops); | |
5b1158e9 JK |
158 | } |
159 | ||
c7232c99 PM |
160 | module_init(iptable_nat_init); |
161 | module_exit(iptable_nat_exit); | |
5b1158e9 JK |
162 | |
163 | MODULE_LICENSE("GPL"); |