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 | */ | |
12 | ||
13 | #include <linux/config.h> | |
14 | #include <linux/ip.h> | |
15 | #include <linux/module.h> | |
16 | #include <linux/netdevice.h> | |
17 | #include <linux/netfilter.h> | |
18 | #include <linux/netfilter_ipv4.h> | |
19 | #include <linux/netfilter_ipv4/ip_nat_rule.h> | |
20 | ||
21 | #define MODULENAME "NETMAP" | |
22 | MODULE_LICENSE("GPL"); | |
23 | MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); | |
24 | MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target"); | |
25 | ||
26 | #if 0 | |
27 | #define DEBUGP printk | |
28 | #else | |
29 | #define DEBUGP(format, args...) | |
30 | #endif | |
31 | ||
32 | static int | |
33 | check(const char *tablename, | |
2e4e6a17 | 34 | const void *e, |
c4986734 | 35 | const struct xt_target *target, |
1da177e4 LT |
36 | void *targinfo, |
37 | unsigned int targinfosize, | |
38 | unsigned int hook_mask) | |
39 | { | |
40 | const struct ip_nat_multi_range_compat *mr = targinfo; | |
41 | ||
1da177e4 LT |
42 | if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { |
43 | DEBUGP(MODULENAME":check: bad MAP_IPS.\n"); | |
44 | return 0; | |
45 | } | |
46 | if (mr->rangesize != 1) { | |
47 | DEBUGP(MODULENAME":check: bad rangesize %u.\n", mr->rangesize); | |
48 | return 0; | |
49 | } | |
50 | return 1; | |
51 | } | |
52 | ||
53 | static unsigned int | |
54 | target(struct sk_buff **pskb, | |
55 | const struct net_device *in, | |
56 | const struct net_device *out, | |
57 | unsigned int hooknum, | |
c4986734 | 58 | const struct xt_target *target, |
1da177e4 LT |
59 | const void *targinfo, |
60 | void *userinfo) | |
61 | { | |
62 | struct ip_conntrack *ct; | |
63 | enum ip_conntrack_info ctinfo; | |
64 | u_int32_t new_ip, netmask; | |
65 | const struct ip_nat_multi_range_compat *mr = targinfo; | |
66 | struct ip_nat_range newrange; | |
67 | ||
68 | IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING | |
000efe1d GWS |
69 | || hooknum == NF_IP_POST_ROUTING |
70 | || hooknum == NF_IP_LOCAL_OUT); | |
1da177e4 LT |
71 | ct = ip_conntrack_get(*pskb, &ctinfo); |
72 | ||
73 | netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); | |
74 | ||
000efe1d | 75 | if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) |
1da177e4 LT |
76 | new_ip = (*pskb)->nh.iph->daddr & ~netmask; |
77 | else | |
78 | new_ip = (*pskb)->nh.iph->saddr & ~netmask; | |
79 | new_ip |= mr->range[0].min_ip & netmask; | |
80 | ||
81 | newrange = ((struct ip_nat_range) | |
82 | { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, | |
83 | new_ip, new_ip, | |
84 | mr->range[0].min, mr->range[0].max }); | |
85 | ||
86 | /* Hand modified range to generic setup. */ | |
87 | return ip_nat_setup_info(ct, &newrange, hooknum); | |
88 | } | |
89 | ||
90 | static struct ipt_target target_module = { | |
91 | .name = MODULENAME, | |
92 | .target = target, | |
1d5cd909 PM |
93 | .targetsize = sizeof(struct ip_nat_multi_range_compat), |
94 | .table = "nat", | |
95 | .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) | | |
96 | (1 << NF_IP_LOCAL_OUT), | |
1da177e4 LT |
97 | .checkentry = check, |
98 | .me = THIS_MODULE | |
99 | }; | |
100 | ||
101 | static int __init init(void) | |
102 | { | |
103 | return ipt_register_target(&target_module); | |
104 | } | |
105 | ||
106 | static void __exit fini(void) | |
107 | { | |
108 | ipt_unregister_target(&target_module); | |
109 | } | |
110 | ||
111 | module_init(init); | |
112 | module_exit(fini); |