1// SPDX-License-Identifier: GPL-2.0-only
2/* Masquerade.  Simple mapping which alters range to a local IP address
3   (depending on route). */
4
5/* (C) 1999-2001 Paul `Rusty' Russell
6 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
7 */
8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9#include <linux/module.h>
10#include <linux/netfilter/x_tables.h>
11#include <net/netfilter/nf_nat.h>
12#include <net/netfilter/nf_nat_masquerade.h>
13
14MODULE_LICENSE("GPL");
15MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
16MODULE_DESCRIPTION("Xtables: automatic-address SNAT");
17
18/* FIXME: Multiple targets. --RR */
19static int masquerade_tg_check(const struct xt_tgchk_param *par)
20{
21	const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
22
23	if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) {
24		pr_debug("bad MAP_IPS.\n");
25		return -EINVAL;
26	}
27	if (mr->rangesize != 1) {
28		pr_debug("bad rangesize %u\n", mr->rangesize);
29		return -EINVAL;
30	}
31	return nf_ct_netns_get(par->net, par->family);
32}
33
34static unsigned int
35masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
36{
37	struct nf_nat_range2 range;
38	const struct nf_nat_ipv4_multi_range_compat *mr;
39
40	mr = par->targinfo;
41	range.flags = mr->range[0].flags;
42	range.min_proto = mr->range[0].min;
43	range.max_proto = mr->range[0].max;
44
45	return nf_nat_masquerade_ipv4(skb, xt_hooknum(par), &range,
46				      xt_out(par));
47}
48
49static void masquerade_tg_destroy(const struct xt_tgdtor_param *par)
50{
51	nf_ct_netns_put(par->net, par->family);
52}
53
54#if IS_ENABLED(CONFIG_IPV6)
55static unsigned int
56masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par)
57{
58	return nf_nat_masquerade_ipv6(skb, par->targinfo, xt_out(par));
59}
60
61static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
62{
63	const struct nf_nat_range2 *range = par->targinfo;
64
65	if (range->flags & NF_NAT_RANGE_MAP_IPS)
66		return -EINVAL;
67
68	return nf_ct_netns_get(par->net, par->family);
69}
70#endif
71
72static struct xt_target masquerade_tg_reg[] __read_mostly = {
73	{
74#if IS_ENABLED(CONFIG_IPV6)
75		.name		= "MASQUERADE",
76		.family		= NFPROTO_IPV6,
77		.target		= masquerade_tg6,
78		.targetsize	= sizeof(struct nf_nat_range),
79		.table		= "nat",
80		.hooks		= 1 << NF_INET_POST_ROUTING,
81		.checkentry	= masquerade_tg6_checkentry,
82		.destroy	= masquerade_tg_destroy,
83		.me		= THIS_MODULE,
84	}, {
85#endif
86		.name		= "MASQUERADE",
87		.family		= NFPROTO_IPV4,
88		.target		= masquerade_tg,
89		.targetsize	= sizeof(struct nf_nat_ipv4_multi_range_compat),
90		.table		= "nat",
91		.hooks		= 1 << NF_INET_POST_ROUTING,
92		.checkentry	= masquerade_tg_check,
93		.destroy	= masquerade_tg_destroy,
94		.me		= THIS_MODULE,
95	}
96};
97
98static int __init masquerade_tg_init(void)
99{
100	int ret;
101
102	ret = xt_register_targets(masquerade_tg_reg,
103				  ARRAY_SIZE(masquerade_tg_reg));
104	if (ret)
105		return ret;
106
107	ret = nf_nat_masquerade_inet_register_notifiers();
108	if (ret) {
109		xt_unregister_targets(masquerade_tg_reg,
110				      ARRAY_SIZE(masquerade_tg_reg));
111		return ret;
112	}
113
114	return ret;
115}
116
117static void __exit masquerade_tg_exit(void)
118{
119	xt_unregister_targets(masquerade_tg_reg, ARRAY_SIZE(masquerade_tg_reg));
120	nf_nat_masquerade_inet_unregister_notifiers();
121}
122
123module_init(masquerade_tg_init);
124module_exit(masquerade_tg_exit);
125#if IS_ENABLED(CONFIG_IPV6)
126MODULE_ALIAS("ip6t_MASQUERADE");
127#endif
128MODULE_ALIAS("ipt_MASQUERADE");
129