Linux-libre 4.19.20-gnu
[librecmc/linux-libre.git] / net / netfilter / xt_nat.c
1 /*
2  * (C) 1999-2001 Paul `Rusty' Russell
3  * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
4  * (C) 2011 Patrick McHardy <kaber@trash.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12
13 #include <linux/module.h>
14 #include <linux/skbuff.h>
15 #include <linux/netfilter.h>
16 #include <linux/netfilter/x_tables.h>
17 #include <net/netfilter/nf_nat_core.h>
18
19 static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par)
20 {
21         const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
22
23         if (mr->rangesize != 1) {
24                 pr_info_ratelimited("multiple ranges no longer supported\n");
25                 return -EINVAL;
26         }
27         return nf_ct_netns_get(par->net, par->family);
28 }
29
30 static int xt_nat_checkentry(const struct xt_tgchk_param *par)
31 {
32         return nf_ct_netns_get(par->net, par->family);
33 }
34
35 static void xt_nat_destroy(const struct xt_tgdtor_param *par)
36 {
37         nf_ct_netns_put(par->net, par->family);
38 }
39
40 static void xt_nat_convert_range(struct nf_nat_range2 *dst,
41                                  const struct nf_nat_ipv4_range *src)
42 {
43         memset(&dst->min_addr, 0, sizeof(dst->min_addr));
44         memset(&dst->max_addr, 0, sizeof(dst->max_addr));
45         memset(&dst->base_proto, 0, sizeof(dst->base_proto));
46
47         dst->flags       = src->flags;
48         dst->min_addr.ip = src->min_ip;
49         dst->max_addr.ip = src->max_ip;
50         dst->min_proto   = src->min;
51         dst->max_proto   = src->max;
52 }
53
54 static unsigned int
55 xt_snat_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
56 {
57         const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
58         struct nf_nat_range2 range;
59         enum ip_conntrack_info ctinfo;
60         struct nf_conn *ct;
61
62         ct = nf_ct_get(skb, &ctinfo);
63         WARN_ON(!(ct != NULL &&
64                  (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
65                   ctinfo == IP_CT_RELATED_REPLY)));
66
67         xt_nat_convert_range(&range, &mr->range[0]);
68         return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
69 }
70
71 static unsigned int
72 xt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
73 {
74         const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
75         struct nf_nat_range2 range;
76         enum ip_conntrack_info ctinfo;
77         struct nf_conn *ct;
78
79         ct = nf_ct_get(skb, &ctinfo);
80         WARN_ON(!(ct != NULL &&
81                  (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
82
83         xt_nat_convert_range(&range, &mr->range[0]);
84         return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
85 }
86
87 static unsigned int
88 xt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
89 {
90         const struct nf_nat_range *range_v1 = par->targinfo;
91         struct nf_nat_range2 range;
92         enum ip_conntrack_info ctinfo;
93         struct nf_conn *ct;
94
95         ct = nf_ct_get(skb, &ctinfo);
96         WARN_ON(!(ct != NULL &&
97                  (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
98                   ctinfo == IP_CT_RELATED_REPLY)));
99
100         memcpy(&range, range_v1, sizeof(*range_v1));
101         memset(&range.base_proto, 0, sizeof(range.base_proto));
102
103         return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
104 }
105
106 static unsigned int
107 xt_dnat_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
108 {
109         const struct nf_nat_range *range_v1 = par->targinfo;
110         struct nf_nat_range2 range;
111         enum ip_conntrack_info ctinfo;
112         struct nf_conn *ct;
113
114         ct = nf_ct_get(skb, &ctinfo);
115         WARN_ON(!(ct != NULL &&
116                  (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
117
118         memcpy(&range, range_v1, sizeof(*range_v1));
119         memset(&range.base_proto, 0, sizeof(range.base_proto));
120
121         return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
122 }
123
124 static unsigned int
125 xt_snat_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
126 {
127         const struct nf_nat_range2 *range = par->targinfo;
128         enum ip_conntrack_info ctinfo;
129         struct nf_conn *ct;
130
131         ct = nf_ct_get(skb, &ctinfo);
132         WARN_ON(!(ct != NULL &&
133                  (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
134                   ctinfo == IP_CT_RELATED_REPLY)));
135
136         return nf_nat_setup_info(ct, range, NF_NAT_MANIP_SRC);
137 }
138
139 static unsigned int
140 xt_dnat_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
141 {
142         const struct nf_nat_range2 *range = par->targinfo;
143         enum ip_conntrack_info ctinfo;
144         struct nf_conn *ct;
145
146         ct = nf_ct_get(skb, &ctinfo);
147         WARN_ON(!(ct != NULL &&
148                  (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
149
150         return nf_nat_setup_info(ct, range, NF_NAT_MANIP_DST);
151 }
152
153 static struct xt_target xt_nat_target_reg[] __read_mostly = {
154         {
155                 .name           = "SNAT",
156                 .revision       = 0,
157                 .checkentry     = xt_nat_checkentry_v0,
158                 .destroy        = xt_nat_destroy,
159                 .target         = xt_snat_target_v0,
160                 .targetsize     = sizeof(struct nf_nat_ipv4_multi_range_compat),
161                 .family         = NFPROTO_IPV4,
162                 .table          = "nat",
163                 .hooks          = (1 << NF_INET_POST_ROUTING) |
164                                   (1 << NF_INET_LOCAL_IN),
165                 .me             = THIS_MODULE,
166         },
167         {
168                 .name           = "DNAT",
169                 .revision       = 0,
170                 .checkentry     = xt_nat_checkentry_v0,
171                 .destroy        = xt_nat_destroy,
172                 .target         = xt_dnat_target_v0,
173                 .targetsize     = sizeof(struct nf_nat_ipv4_multi_range_compat),
174                 .family         = NFPROTO_IPV4,
175                 .table          = "nat",
176                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
177                                   (1 << NF_INET_LOCAL_OUT),
178                 .me             = THIS_MODULE,
179         },
180         {
181                 .name           = "SNAT",
182                 .revision       = 1,
183                 .checkentry     = xt_nat_checkentry,
184                 .destroy        = xt_nat_destroy,
185                 .target         = xt_snat_target_v1,
186                 .targetsize     = sizeof(struct nf_nat_range),
187                 .table          = "nat",
188                 .hooks          = (1 << NF_INET_POST_ROUTING) |
189                                   (1 << NF_INET_LOCAL_IN),
190                 .me             = THIS_MODULE,
191         },
192         {
193                 .name           = "DNAT",
194                 .revision       = 1,
195                 .checkentry     = xt_nat_checkentry,
196                 .destroy        = xt_nat_destroy,
197                 .target         = xt_dnat_target_v1,
198                 .targetsize     = sizeof(struct nf_nat_range),
199                 .table          = "nat",
200                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
201                                   (1 << NF_INET_LOCAL_OUT),
202                 .me             = THIS_MODULE,
203         },
204         {
205                 .name           = "SNAT",
206                 .revision       = 2,
207                 .checkentry     = xt_nat_checkentry,
208                 .destroy        = xt_nat_destroy,
209                 .target         = xt_snat_target_v2,
210                 .targetsize     = sizeof(struct nf_nat_range2),
211                 .table          = "nat",
212                 .hooks          = (1 << NF_INET_POST_ROUTING) |
213                                   (1 << NF_INET_LOCAL_IN),
214                 .me             = THIS_MODULE,
215         },
216         {
217                 .name           = "DNAT",
218                 .revision       = 2,
219                 .checkentry     = xt_nat_checkentry,
220                 .destroy        = xt_nat_destroy,
221                 .target         = xt_dnat_target_v2,
222                 .targetsize     = sizeof(struct nf_nat_range2),
223                 .table          = "nat",
224                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
225                                   (1 << NF_INET_LOCAL_OUT),
226                 .me             = THIS_MODULE,
227         },
228 };
229
230 static int __init xt_nat_init(void)
231 {
232         return xt_register_targets(xt_nat_target_reg,
233                                    ARRAY_SIZE(xt_nat_target_reg));
234 }
235
236 static void __exit xt_nat_exit(void)
237 {
238         xt_unregister_targets(xt_nat_target_reg, ARRAY_SIZE(xt_nat_target_reg));
239 }
240
241 module_init(xt_nat_init);
242 module_exit(xt_nat_exit);
243
244 MODULE_LICENSE("GPL");
245 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
246 MODULE_ALIAS("ipt_SNAT");
247 MODULE_ALIAS("ipt_DNAT");
248 MODULE_ALIAS("ip6t_SNAT");
249 MODULE_ALIAS("ip6t_DNAT");