1c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy/*
2c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy * (C) 1999-2001 Paul `Rusty' Russell
3c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
4c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy * (C) 2011 Patrick McHardy <kaber@trash.net>
5c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy *
6c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy * This program is free software; you can redistribute it and/or modify
7c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy * it under the terms of the GNU General Public License version 2 as
8c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy * published by the Free Software Foundation.
9c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy */
10c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
11c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy#include <linux/module.h>
12c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy#include <linux/skbuff.h>
13c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy#include <linux/netfilter.h>
14c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy#include <linux/netfilter/x_tables.h>
15c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy#include <net/netfilter/nf_nat_core.h>
16c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
17c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardystatic int xt_nat_checkentry_v0(const struct xt_tgchk_param *par)
18c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy{
19c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
20c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
21c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	if (mr->rangesize != 1) {
22c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		pr_info("%s: multiple ranges no longer supported\n",
23c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy			par->target->name);
24c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		return -EINVAL;
25c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	}
26c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	return 0;
27c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy}
28c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
29c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardystatic void xt_nat_convert_range(struct nf_nat_range *dst,
30c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy				 const struct nf_nat_ipv4_range *src)
31c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy{
32c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	memset(&dst->min_addr, 0, sizeof(dst->min_addr));
33c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	memset(&dst->max_addr, 0, sizeof(dst->max_addr));
34c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
35c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	dst->flags	 = src->flags;
36c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	dst->min_addr.ip = src->min_ip;
37c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	dst->max_addr.ip = src->max_ip;
38c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	dst->min_proto	 = src->min;
39c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	dst->max_proto	 = src->max;
40c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy}
41c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
42c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardystatic unsigned int
43c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardyxt_snat_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
44c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy{
45c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
46c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	struct nf_nat_range range;
47c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	enum ip_conntrack_info ctinfo;
48c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	struct nf_conn *ct;
49c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
50c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	ct = nf_ct_get(skb, &ctinfo);
51c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	NF_CT_ASSERT(ct != NULL &&
52c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		     (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
53c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		      ctinfo == IP_CT_RELATED_REPLY));
54c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
55c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	xt_nat_convert_range(&range, &mr->range[0]);
56c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
57c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy}
58c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
59c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardystatic unsigned int
60c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardyxt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
61c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy{
62c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
63c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	struct nf_nat_range range;
64c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	enum ip_conntrack_info ctinfo;
65c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	struct nf_conn *ct;
66c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
67c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	ct = nf_ct_get(skb, &ctinfo);
68c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	NF_CT_ASSERT(ct != NULL &&
69c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		     (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
70c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
71c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	xt_nat_convert_range(&range, &mr->range[0]);
72c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
73c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy}
74c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
75c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardystatic unsigned int
76c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardyxt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
77c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy{
78c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	const struct nf_nat_range *range = par->targinfo;
79c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	enum ip_conntrack_info ctinfo;
80c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	struct nf_conn *ct;
81c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
82c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	ct = nf_ct_get(skb, &ctinfo);
83c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	NF_CT_ASSERT(ct != NULL &&
84c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		     (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
85c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		      ctinfo == IP_CT_RELATED_REPLY));
86c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
87c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	return nf_nat_setup_info(ct, range, NF_NAT_MANIP_SRC);
88c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy}
89c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
90c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardystatic unsigned int
91c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardyxt_dnat_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
92c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy{
93c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	const struct nf_nat_range *range = par->targinfo;
94c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	enum ip_conntrack_info ctinfo;
95c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	struct nf_conn *ct;
96c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
97c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	ct = nf_ct_get(skb, &ctinfo);
98c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	NF_CT_ASSERT(ct != NULL &&
99c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		     (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
100c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
101c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	return nf_nat_setup_info(ct, range, NF_NAT_MANIP_DST);
102c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy}
103c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
104c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardystatic struct xt_target xt_nat_target_reg[] __read_mostly = {
105c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	{
106c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.name		= "SNAT",
107c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.revision	= 0,
108c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.checkentry	= xt_nat_checkentry_v0,
109c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.target		= xt_snat_target_v0,
110c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.targetsize	= sizeof(struct nf_nat_ipv4_multi_range_compat),
111c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.family		= NFPROTO_IPV4,
112c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.table		= "nat",
113c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.hooks		= (1 << NF_INET_POST_ROUTING) |
114939ccba437da1726a5c8a5b702a47d473da927aeElison Niven				  (1 << NF_INET_LOCAL_IN),
115c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.me		= THIS_MODULE,
116c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	},
117c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	{
118c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.name		= "DNAT",
119c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.revision	= 0,
120c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.checkentry	= xt_nat_checkentry_v0,
121c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.target		= xt_dnat_target_v0,
122c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.targetsize	= sizeof(struct nf_nat_ipv4_multi_range_compat),
123c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.family		= NFPROTO_IPV4,
124c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.table		= "nat",
125c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.hooks		= (1 << NF_INET_PRE_ROUTING) |
126939ccba437da1726a5c8a5b702a47d473da927aeElison Niven				  (1 << NF_INET_LOCAL_OUT),
127c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.me		= THIS_MODULE,
128c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	},
129c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	{
130c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.name		= "SNAT",
131c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.revision	= 1,
132c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.target		= xt_snat_target_v1,
133c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.targetsize	= sizeof(struct nf_nat_range),
134c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.table		= "nat",
135c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.hooks		= (1 << NF_INET_POST_ROUTING) |
136939ccba437da1726a5c8a5b702a47d473da927aeElison Niven				  (1 << NF_INET_LOCAL_IN),
137c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.me		= THIS_MODULE,
138c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	},
139c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	{
140c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.name		= "DNAT",
141c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.revision	= 1,
142c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.target		= xt_dnat_target_v1,
143c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.targetsize	= sizeof(struct nf_nat_range),
144c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.table		= "nat",
145c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.hooks		= (1 << NF_INET_PRE_ROUTING) |
146939ccba437da1726a5c8a5b702a47d473da927aeElison Niven				  (1 << NF_INET_LOCAL_OUT),
147c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy		.me		= THIS_MODULE,
148c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	},
149c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy};
150c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
151c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardystatic int __init xt_nat_init(void)
152c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy{
153c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	return xt_register_targets(xt_nat_target_reg,
154c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy				   ARRAY_SIZE(xt_nat_target_reg));
155c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy}
156c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
157c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardystatic void __exit xt_nat_exit(void)
158c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy{
159c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy	xt_unregister_targets(xt_nat_target_reg, ARRAY_SIZE(xt_nat_target_reg));
160c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy}
161c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
162c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardymodule_init(xt_nat_init);
163c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardymodule_exit(xt_nat_exit);
164c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardy
165c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardyMODULE_LICENSE("GPL");
16658a317f1061c894d2344c0b6a18ab4a64b69b815Patrick McHardyMODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
167c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardyMODULE_ALIAS("ipt_SNAT");
168c7232c9979cba684c50b64c513c4a83c9aa70563Patrick McHardyMODULE_ALIAS("ipt_DNAT");
16958a317f1061c894d2344c0b6a18ab4a64b69b815Patrick McHardyMODULE_ALIAS("ip6t_SNAT");
17058a317f1061c894d2344c0b6a18ab4a64b69b815Patrick McHardyMODULE_ALIAS("ip6t_DNAT");
171