1 // SPDX-License-Identifier: GPL-2.0-only
3 * (C) 2000-2001 Svenning Soerensen <svenning@post5.tele.dk>
4 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/netdevice.h>
11 #include <linux/ipv6.h>
12 #include <linux/netfilter.h>
13 #include <linux/netfilter_ipv4.h>
14 #include <linux/netfilter_ipv6.h>
15 #include <linux/netfilter/x_tables.h>
16 #include <net/netfilter/nf_nat.h>
19 netmap_tg6(struct sk_buff
*skb
, const struct xt_action_param
*par
)
21 const struct nf_nat_range2
*range
= par
->targinfo
;
22 struct nf_nat_range2 newrange
;
24 enum ip_conntrack_info ctinfo
;
25 union nf_inet_addr new_addr
, netmask
;
28 ct
= nf_ct_get(skb
, &ctinfo
);
29 for (i
= 0; i
< ARRAY_SIZE(range
->min_addr
.ip6
); i
++)
30 netmask
.ip6
[i
] = ~(range
->min_addr
.ip6
[i
] ^
31 range
->max_addr
.ip6
[i
]);
33 if (xt_hooknum(par
) == NF_INET_PRE_ROUTING
||
34 xt_hooknum(par
) == NF_INET_LOCAL_OUT
)
35 new_addr
.in6
= ipv6_hdr(skb
)->daddr
;
37 new_addr
.in6
= ipv6_hdr(skb
)->saddr
;
39 for (i
= 0; i
< ARRAY_SIZE(new_addr
.ip6
); i
++) {
40 new_addr
.ip6
[i
] &= ~netmask
.ip6
[i
];
41 new_addr
.ip6
[i
] |= range
->min_addr
.ip6
[i
] &
45 newrange
.flags
= range
->flags
| NF_NAT_RANGE_MAP_IPS
;
46 newrange
.min_addr
= new_addr
;
47 newrange
.max_addr
= new_addr
;
48 newrange
.min_proto
= range
->min_proto
;
49 newrange
.max_proto
= range
->max_proto
;
51 return nf_nat_setup_info(ct
, &newrange
, HOOK2MANIP(xt_hooknum(par
)));
54 static int netmap_tg6_checkentry(const struct xt_tgchk_param
*par
)
56 const struct nf_nat_range2
*range
= par
->targinfo
;
58 if (!(range
->flags
& NF_NAT_RANGE_MAP_IPS
))
60 return nf_ct_netns_get(par
->net
, par
->family
);
63 static void netmap_tg_destroy(const struct xt_tgdtor_param
*par
)
65 nf_ct_netns_put(par
->net
, par
->family
);
69 netmap_tg4(struct sk_buff
*skb
, const struct xt_action_param
*par
)
72 enum ip_conntrack_info ctinfo
;
73 __be32 new_ip
, netmask
;
74 const struct nf_nat_ipv4_multi_range_compat
*mr
= par
->targinfo
;
75 struct nf_nat_range2 newrange
;
77 WARN_ON(xt_hooknum(par
) != NF_INET_PRE_ROUTING
&&
78 xt_hooknum(par
) != NF_INET_POST_ROUTING
&&
79 xt_hooknum(par
) != NF_INET_LOCAL_OUT
&&
80 xt_hooknum(par
) != NF_INET_LOCAL_IN
);
81 ct
= nf_ct_get(skb
, &ctinfo
);
83 netmask
= ~(mr
->range
[0].min_ip
^ mr
->range
[0].max_ip
);
85 if (xt_hooknum(par
) == NF_INET_PRE_ROUTING
||
86 xt_hooknum(par
) == NF_INET_LOCAL_OUT
)
87 new_ip
= ip_hdr(skb
)->daddr
& ~netmask
;
89 new_ip
= ip_hdr(skb
)->saddr
& ~netmask
;
90 new_ip
|= mr
->range
[0].min_ip
& netmask
;
92 memset(&newrange
.min_addr
, 0, sizeof(newrange
.min_addr
));
93 memset(&newrange
.max_addr
, 0, sizeof(newrange
.max_addr
));
94 newrange
.flags
= mr
->range
[0].flags
| NF_NAT_RANGE_MAP_IPS
;
95 newrange
.min_addr
.ip
= new_ip
;
96 newrange
.max_addr
.ip
= new_ip
;
97 newrange
.min_proto
= mr
->range
[0].min
;
98 newrange
.max_proto
= mr
->range
[0].max
;
100 /* Hand modified range to generic setup. */
101 return nf_nat_setup_info(ct
, &newrange
, HOOK2MANIP(xt_hooknum(par
)));
104 static int netmap_tg4_check(const struct xt_tgchk_param
*par
)
106 const struct nf_nat_ipv4_multi_range_compat
*mr
= par
->targinfo
;
108 if (!(mr
->range
[0].flags
& NF_NAT_RANGE_MAP_IPS
)) {
109 pr_debug("bad MAP_IPS.\n");
112 if (mr
->rangesize
!= 1) {
113 pr_debug("bad rangesize %u.\n", mr
->rangesize
);
116 return nf_ct_netns_get(par
->net
, par
->family
);
119 static struct xt_target netmap_tg_reg
[] __read_mostly
= {
122 .family
= NFPROTO_IPV6
,
124 .target
= netmap_tg6
,
125 .targetsize
= sizeof(struct nf_nat_range
),
127 .hooks
= (1 << NF_INET_PRE_ROUTING
) |
128 (1 << NF_INET_POST_ROUTING
) |
129 (1 << NF_INET_LOCAL_OUT
) |
130 (1 << NF_INET_LOCAL_IN
),
131 .checkentry
= netmap_tg6_checkentry
,
132 .destroy
= netmap_tg_destroy
,
137 .family
= NFPROTO_IPV4
,
139 .target
= netmap_tg4
,
140 .targetsize
= sizeof(struct nf_nat_ipv4_multi_range_compat
),
142 .hooks
= (1 << NF_INET_PRE_ROUTING
) |
143 (1 << NF_INET_POST_ROUTING
) |
144 (1 << NF_INET_LOCAL_OUT
) |
145 (1 << NF_INET_LOCAL_IN
),
146 .checkentry
= netmap_tg4_check
,
147 .destroy
= netmap_tg_destroy
,
152 static int __init
netmap_tg_init(void)
154 return xt_register_targets(netmap_tg_reg
, ARRAY_SIZE(netmap_tg_reg
));
157 static void netmap_tg_exit(void)
159 xt_unregister_targets(netmap_tg_reg
, ARRAY_SIZE(netmap_tg_reg
));
162 module_init(netmap_tg_init
);
163 module_exit(netmap_tg_exit
);
165 MODULE_LICENSE("GPL");
166 MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of subnets");
167 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
168 MODULE_ALIAS("ip6t_NETMAP");
169 MODULE_ALIAS("ipt_NETMAP");