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