]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* NETMAP - static NAT mapping of IP network addresses (1:1). |
2 | * The mapping can be applied to source (POSTROUTING), | |
3 | * destination (PREROUTING), or both (with separate rules). | |
4 | */ | |
5 | ||
6 | /* (C) 2000-2001 Svenning Soerensen <svenning@post5.tele.dk> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | */ | |
ff67e4e4 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
1da177e4 LT |
13 | #include <linux/ip.h> |
14 | #include <linux/module.h> | |
15 | #include <linux/netdevice.h> | |
16 | #include <linux/netfilter.h> | |
17 | #include <linux/netfilter_ipv4.h> | |
6709dbbb | 18 | #include <linux/netfilter/x_tables.h> |
5b1158e9 | 19 | #include <net/netfilter/nf_nat_rule.h> |
1da177e4 | 20 | |
1da177e4 LT |
21 | MODULE_LICENSE("GPL"); |
22 | MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); | |
2ae15b64 | 23 | MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets"); |
1da177e4 | 24 | |
135367b8 | 25 | static int netmap_tg_check(const struct xt_tgchk_param *par) |
1da177e4 | 26 | { |
af5d6dc2 | 27 | const struct nf_nat_multi_range_compat *mr = par->targinfo; |
1da177e4 | 28 | |
1da177e4 | 29 | if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { |
ff67e4e4 | 30 | pr_debug("bad MAP_IPS.\n"); |
d6b00a53 | 31 | return -EINVAL; |
1da177e4 LT |
32 | } |
33 | if (mr->rangesize != 1) { | |
ff67e4e4 | 34 | pr_debug("bad rangesize %u.\n", mr->rangesize); |
d6b00a53 | 35 | return -EINVAL; |
1da177e4 | 36 | } |
d6b00a53 | 37 | return 0; |
1da177e4 LT |
38 | } |
39 | ||
40 | static unsigned int | |
4b560b44 | 41 | netmap_tg(struct sk_buff *skb, const struct xt_action_param *par) |
1da177e4 | 42 | { |
587aa641 | 43 | struct nf_conn *ct; |
1da177e4 | 44 | enum ip_conntrack_info ctinfo; |
6a19d614 | 45 | __be32 new_ip, netmask; |
7eb35586 | 46 | const struct nf_nat_multi_range_compat *mr = par->targinfo; |
587aa641 | 47 | struct nf_nat_range newrange; |
1da177e4 | 48 | |
7eb35586 JE |
49 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || |
50 | par->hooknum == NF_INET_POST_ROUTING || | |
51 | par->hooknum == NF_INET_LOCAL_OUT); | |
3db05fea | 52 | ct = nf_ct_get(skb, &ctinfo); |
1da177e4 LT |
53 | |
54 | netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); | |
55 | ||
7eb35586 JE |
56 | if (par->hooknum == NF_INET_PRE_ROUTING || |
57 | par->hooknum == NF_INET_LOCAL_OUT) | |
3db05fea | 58 | new_ip = ip_hdr(skb)->daddr & ~netmask; |
1da177e4 | 59 | else |
3db05fea | 60 | new_ip = ip_hdr(skb)->saddr & ~netmask; |
1da177e4 LT |
61 | new_ip |= mr->range[0].min_ip & netmask; |
62 | ||
587aa641 | 63 | newrange = ((struct nf_nat_range) |
1da177e4 LT |
64 | { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, |
65 | new_ip, new_ip, | |
66 | mr->range[0].min, mr->range[0].max }); | |
67 | ||
68 | /* Hand modified range to generic setup. */ | |
7eb35586 | 69 | return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); |
1da177e4 LT |
70 | } |
71 | ||
d3c5ee6d | 72 | static struct xt_target netmap_tg_reg __read_mostly = { |
0d53778e | 73 | .name = "NETMAP", |
ee999d8b | 74 | .family = NFPROTO_IPV4, |
d3c5ee6d | 75 | .target = netmap_tg, |
587aa641 | 76 | .targetsize = sizeof(struct nf_nat_multi_range_compat), |
1d5cd909 | 77 | .table = "nat", |
6e23ae2a PM |
78 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
79 | (1 << NF_INET_POST_ROUTING) | | |
80 | (1 << NF_INET_LOCAL_OUT), | |
d3c5ee6d | 81 | .checkentry = netmap_tg_check, |
e905a9ed | 82 | .me = THIS_MODULE |
1da177e4 LT |
83 | }; |
84 | ||
d3c5ee6d | 85 | static int __init netmap_tg_init(void) |
1da177e4 | 86 | { |
d3c5ee6d | 87 | return xt_register_target(&netmap_tg_reg); |
1da177e4 LT |
88 | } |
89 | ||
d3c5ee6d | 90 | static void __exit netmap_tg_exit(void) |
1da177e4 | 91 | { |
d3c5ee6d | 92 | xt_unregister_target(&netmap_tg_reg); |
1da177e4 LT |
93 | } |
94 | ||
d3c5ee6d JE |
95 | module_init(netmap_tg_init); |
96 | module_exit(netmap_tg_exit); |