xref: /openbmc/linux/net/netfilter/xt_nat.c (revision 96ac6d43)
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.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");
250