allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / net / ipv4 / netfilter / nf_nat_autofw.c
blobb22445c878093a1900fc8576f141adc0732c1326
1 /*
2 * Automatic port forwarding target. When this target is entered, a
3 * related connection to a port in the reply direction will be
4 * expected. This connection may be mapped to a different port.
6 * Copyright (C) 2008, Broadcom Corporation
7 * All Rights Reserved.
8 *
9 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
10 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
11 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
12 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
14 * $Id: nf_nat_autofw.c,v 1.1 2008/10/02 03:40:29 Exp $
17 #include <linux/config.h>
18 #include <linux/types.h>
19 #include <linux/ip.h>
20 #include <linux/timer.h>
21 #include <linux/module.h>
22 #include <linux/netfilter.h>
23 #include <net/protocol.h>
24 #include <net/checksum.h>
25 #include <net/tcp.h>
27 #include <linux/netfilter_ipv4.h>
28 #include <linux/netfilter_ipv4/ip_tables.h>
29 #include <net/netfilter/nf_nat_rule.h>
30 #include <linux/netfilter/x_tables.h>
32 #include <net/netfilter/nf_conntrack_expect.h>
33 #include <net/netfilter/nf_conntrack_helper.h>
34 #include <linux/netfilter_ipv4/ip_autofw.h>
36 DEFINE_RWLOCK(nf_nat_autofw_lock);
38 #define DEBUGP(format, args...)
40 static int
41 autofw_help(struct sk_buff *skb,
42 unsigned int protoff,
43 struct nf_conn *ct,
44 enum ip_conntrack_info ctinfo)
46 return 1;
49 static void
50 autofw_expect(struct nf_conn *ct, struct nf_conntrack_expect *exp)
52 struct nf_nat_range pre_range;
53 u_int32_t newdstip, newsrcip;
54 u_int16_t port;
55 int ret;
56 struct nf_conn_help *help;
57 struct nf_conn *exp_ct = exp->master;
58 struct nf_conntrack_expect *newexp;
59 int count;
61 /* expect has been removed from expect list, but expect isn't free yet. */
62 help = nfct_help(exp_ct);
63 DEBUGP("autofw_nat_expected: got ");
64 NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
66 spin_lock_bh(&nf_nat_autofw_lock);
68 port = ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.all);
69 newdstip = exp->tuple.dst.u3.ip;
70 newsrcip = exp->tuple.src.u3.ip;
71 if (port < ntohs(help->help.ct_autofw_info.dport[0]) ||
72 port > ntohs(help->help.ct_autofw_info.dport[1])) {
73 spin_unlock_bh(&nf_nat_autofw_lock);
74 return;
77 /* Only need to do PRE_ROUTING */
78 port -= ntohs(help->help.ct_autofw_info.dport[0]);
79 port += ntohs(help->help.ct_autofw_info.to[0]);
80 pre_range.flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
81 pre_range.min_ip = pre_range.max_ip = newdstip;
82 pre_range.min.all = pre_range.max.all = htons(port);
83 nf_nat_setup_info(ct, &pre_range, NF_IP_PRE_ROUTING);
85 spin_unlock_bh(&nf_nat_autofw_lock);
87 /* Add expect again */
89 /* alloc will set exp->master = exp_ct */
90 newexp = nf_conntrack_expect_alloc(exp_ct);
91 if (!newexp)
92 return;
94 newexp->tuple.src.u3.ip = exp->tuple.src.u3.ip;
95 newexp->tuple.dst.protonum = exp->tuple.dst.protonum;
96 newexp->mask.src.u3.ip = 0xFFFFFFFF;
97 newexp->mask.dst.protonum = 0xFF;
99 newexp->tuple.dst.u3.ip = exp->tuple.dst.u3.ip;
100 newexp->mask.dst.u3.ip = 0x0;
102 for (count = 1; count < NF_CT_TUPLE_L3SIZE; count++) {
103 newexp->tuple.src.u3.all[count] = 0x0;
104 newexp->tuple.dst.u3.all[count] = 0x0;
107 newexp->mask.dst.u.all = 0x0;
108 newexp->mask.src.u.all = 0x0;
109 newexp->mask.src.l3num = 0x0;
111 newexp->expectfn = autofw_expect;
112 newexp->helper = NULL;
113 newexp->flags = 0;
114 newexp->class = NF_CT_EXPECT_CLASS_DEFAULT;
117 * exp->timeout.expires will set as
118 * (jiffies + helper->timeout * HZ), when insert exp.
120 ret = nf_conntrack_expect_related(newexp);
121 if (ret == 0)
122 nf_conntrack_expect_put(newexp);
125 static const struct nf_conntrack_expect_policy autofw_exp_policy = {
126 .max_expected = 0,
127 .timeout = 5 * 60,
130 static struct nf_conntrack_helper autofw_helper __read_mostly = {
131 .me = THIS_MODULE,
132 .help = autofw_help,
133 .expect_policy = &autofw_exp_policy,
134 .name = "autofw",
135 .tuple.dst.u3.ip = 0xFFFFFFFF,
136 .tuple.dst.protonum = 0xFF,
137 .mask.dst.u3.ip = 0xFFFFFFFF,
138 .mask.dst.protonum = 0xFF,
139 .tuple.src.u3.ip = 0xFFFFFFFF,
142 static unsigned int
143 autofw_target(struct sk_buff *skb,
144 const struct net_device *in,
145 const struct net_device *out,
146 unsigned int hooknum,
147 const struct xt_target *target,
148 const void *targinfo)
150 const struct ip_autofw_info *info = targinfo;
151 const struct iphdr *iph = ip_hdr(skb);
152 int ret;
153 struct nf_conntrack_helper *helper;
154 struct nf_conntrack_expect *exp;
155 struct nf_conn *ct;
156 enum ip_conntrack_info ctinfo;
157 struct nf_conn_help *help;
158 int count;
160 ct = nf_ct_get(skb, &ctinfo);
161 if (!ct)
162 goto out;
164 helper = __nf_conntrack_helper_find_byname("autofw");
165 if (!helper)
166 goto out;
168 help = nfct_help(ct);
169 help->helper = helper;
171 /* alloc will set exp->master = ct */
172 exp = nf_conntrack_expect_alloc(ct);
173 if (!exp)
174 goto out;
176 exp->tuple.src.u3.ip = iph->daddr;
177 exp->tuple.dst.protonum = info->proto;
178 exp->mask.src.u3.ip = 0xFFFFFFFF;
179 exp->mask.dst.protonum = 0xFF;
181 exp->tuple.dst.u3.ip = iph->saddr;
182 exp->mask.dst.u3.ip = 0x0;
184 for (count = 1; count < NF_CT_TUPLE_L3SIZE; count++) {
185 exp->tuple.src.u3.all[count] = 0x0;
186 exp->tuple.dst.u3.all[count] = 0x0;
189 exp->mask.dst.u.all = 0x0;
190 exp->mask.src.u.all = 0x0;
191 exp->mask.src.l3num = 0x0;
193 exp->expectfn = autofw_expect;
194 exp->helper = NULL;
195 exp->flags = 0;
196 exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
199 * exp->timeout.expires will set as
200 * (jiffies + helper->timeout * HZ), when insert exp.
202 ret = nf_conntrack_expect_related(exp);
203 if (ret != 0)
204 goto out;
206 nf_conntrack_expect_put(exp);
208 help->help.ct_autofw_info.dport[0] = info->dport[0];
209 help->help.ct_autofw_info.dport[1] = info->dport[1];
210 help->help.ct_autofw_info.to[0] = info->to[0];
211 help->help.ct_autofw_info.to[1] = info->to[1];
213 out:
214 return IPT_CONTINUE;
217 static int
218 autofw_check(const char *tablename,
219 const void *e,
220 const struct xt_target *target,
221 void *targinfo,
222 unsigned int hook_mask)
225 const struct ip_autofw_info *info = targinfo;
227 if (info->proto != IPPROTO_TCP && info->proto != IPPROTO_UDP) {
228 DEBUGP("autofw_check: bad proto %d.\n", info->proto);
229 return 0;
232 return 1;
235 static struct xt_target autofw = {
236 .name = "autofw",
237 .family = AF_INET,
238 .target = autofw_target,
239 .targetsize = sizeof(struct ip_autofw_info),
240 .table = "nat",
241 .hooks = 1 << NF_IP_PRE_ROUTING,
242 .checkentry = autofw_check,
243 .me = THIS_MODULE
246 static int __init ip_autofw_init(void)
248 int ret;
250 ret = nf_conntrack_helper_register(&autofw_helper);
251 if (ret < 0)
252 return ret;
254 return xt_register_target(&autofw);
257 static void __exit ip_autofw_fini(void)
259 nf_conntrack_helper_unregister(&autofw_helper);
260 xt_unregister_target(&autofw);
263 module_init(ip_autofw_init);
264 module_exit(ip_autofw_fini);