2 * (C) 2000-2001 Svenning Soerensen <svenning@post5.tele.dk>
3 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/netdevice.h>
14 #include <linux/ipv6.h>
15 #include <linux/netfilter.h>
16 #include <linux/netfilter_ipv4.h>
17 #include <linux/netfilter_ipv6.h>
18 #include <linux/netfilter/x_tables.h>
19 #include <net/netfilter/nf_nat.h>
22 netmap_tg6(struct sk_buff
*skb
, const struct xt_action_param
*par
)
24 const struct nf_nat_range
*range
= par
->targinfo
;
25 struct nf_nat_range newrange
;
27 enum ip_conntrack_info ctinfo
;
28 union nf_inet_addr new_addr
, netmask
;
31 ct
= nf_ct_get(skb
, &ctinfo
);
32 for (i
= 0; i
< ARRAY_SIZE(range
->min_addr
.ip6
); i
++)
33 netmask
.ip6
[i
] = ~(range
->min_addr
.ip6
[i
] ^
34 range
->max_addr
.ip6
[i
]);
36 if (par
->hooknum
== NF_INET_PRE_ROUTING
||
37 par
->hooknum
== NF_INET_LOCAL_OUT
)
38 new_addr
.in6
= ipv6_hdr(skb
)->daddr
;
40 new_addr
.in6
= ipv6_hdr(skb
)->saddr
;
42 for (i
= 0; i
< ARRAY_SIZE(new_addr
.ip6
); i
++) {
43 new_addr
.ip6
[i
] &= ~netmask
.ip6
[i
];
44 new_addr
.ip6
[i
] |= range
->min_addr
.ip6
[i
] &
48 newrange
.flags
= range
->flags
| NF_NAT_RANGE_MAP_IPS
;
49 newrange
.min_addr
= new_addr
;
50 newrange
.max_addr
= new_addr
;
51 newrange
.min_proto
= range
->min_proto
;
52 newrange
.max_proto
= range
->max_proto
;
54 return nf_nat_setup_info(ct
, &newrange
, HOOK2MANIP(par
->hooknum
));
57 static int netmap_tg6_checkentry(const struct xt_tgchk_param
*par
)
59 const struct nf_nat_range
*range
= par
->targinfo
;
61 if (!(range
->flags
& NF_NAT_RANGE_MAP_IPS
))
67 netmap_tg4(struct sk_buff
*skb
, const struct xt_action_param
*par
)
70 enum ip_conntrack_info ctinfo
;
71 __be32 new_ip
, netmask
;
72 const struct nf_nat_ipv4_multi_range_compat
*mr
= par
->targinfo
;
73 struct nf_nat_range newrange
;
75 NF_CT_ASSERT(par
->hooknum
== NF_INET_PRE_ROUTING
||
76 par
->hooknum
== NF_INET_POST_ROUTING
||
77 par
->hooknum
== NF_INET_LOCAL_OUT
||
78 par
->hooknum
== NF_INET_LOCAL_IN
);
79 ct
= nf_ct_get(skb
, &ctinfo
);
81 netmask
= ~(mr
->range
[0].min_ip
^ mr
->range
[0].max_ip
);
83 if (par
->hooknum
== NF_INET_PRE_ROUTING
||
84 par
->hooknum
== NF_INET_LOCAL_OUT
)
85 new_ip
= ip_hdr(skb
)->daddr
& ~netmask
;
87 new_ip
= ip_hdr(skb
)->saddr
& ~netmask
;
88 new_ip
|= mr
->range
[0].min_ip
& netmask
;
90 memset(&newrange
.min_addr
, 0, sizeof(newrange
.min_addr
));
91 memset(&newrange
.max_addr
, 0, sizeof(newrange
.max_addr
));
92 newrange
.flags
= mr
->range
[0].flags
| NF_NAT_RANGE_MAP_IPS
;
93 newrange
.min_addr
.ip
= new_ip
;
94 newrange
.max_addr
.ip
= new_ip
;
95 newrange
.min_proto
= mr
->range
[0].min
;
96 newrange
.max_proto
= mr
->range
[0].max
;
98 /* Hand modified range to generic setup. */
99 return nf_nat_setup_info(ct
, &newrange
, HOOK2MANIP(par
->hooknum
));
102 static int netmap_tg4_check(const struct xt_tgchk_param
*par
)
104 const struct nf_nat_ipv4_multi_range_compat
*mr
= par
->targinfo
;
106 if (!(mr
->range
[0].flags
& NF_NAT_RANGE_MAP_IPS
)) {
107 pr_debug("bad MAP_IPS.\n");
110 if (mr
->rangesize
!= 1) {
111 pr_debug("bad rangesize %u.\n", mr
->rangesize
);
117 static struct xt_target netmap_tg_reg
[] __read_mostly
= {
120 .family
= NFPROTO_IPV6
,
122 .target
= netmap_tg6
,
123 .targetsize
= sizeof(struct nf_nat_range
),
125 .hooks
= (1 << NF_INET_PRE_ROUTING
) |
126 (1 << NF_INET_POST_ROUTING
) |
127 (1 << NF_INET_LOCAL_OUT
) |
128 (1 << NF_INET_LOCAL_IN
),
129 .checkentry
= netmap_tg6_checkentry
,
134 .family
= NFPROTO_IPV4
,
136 .target
= netmap_tg4
,
137 .targetsize
= sizeof(struct nf_nat_ipv4_multi_range_compat
),
139 .hooks
= (1 << NF_INET_PRE_ROUTING
) |
140 (1 << NF_INET_POST_ROUTING
) |
141 (1 << NF_INET_LOCAL_OUT
) |
142 (1 << NF_INET_LOCAL_IN
),
143 .checkentry
= netmap_tg4_check
,
148 static int __init
netmap_tg_init(void)
150 return xt_register_targets(netmap_tg_reg
, ARRAY_SIZE(netmap_tg_reg
));
153 static void netmap_tg_exit(void)
155 xt_unregister_targets(netmap_tg_reg
, ARRAY_SIZE(netmap_tg_reg
));
158 module_init(netmap_tg_init
);
159 module_exit(netmap_tg_exit
);
161 MODULE_LICENSE("GPL");
162 MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of subnets");
163 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
164 MODULE_ALIAS("ip6t_NETMAP");
165 MODULE_ALIAS("ipt_NETMAP");