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
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>
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>
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...)
41 autofw_help(struct sk_buff
*skb
,
44 enum ip_conntrack_info ctinfo
)
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
;
56 struct nf_conn_help
*help
;
57 struct nf_conn
*exp_ct
= exp
->master
;
58 struct nf_conntrack_expect
*newexp
;
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
);
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
);
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
;
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
);
122 nf_conntrack_expect_put(newexp
);
125 static const struct nf_conntrack_expect_policy autofw_exp_policy
= {
130 static struct nf_conntrack_helper autofw_helper __read_mostly
= {
133 .expect_policy
= &autofw_exp_policy
,
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,
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
);
153 struct nf_conntrack_helper
*helper
;
154 struct nf_conntrack_expect
*exp
;
156 enum ip_conntrack_info ctinfo
;
157 struct nf_conn_help
*help
;
160 ct
= nf_ct_get(skb
, &ctinfo
);
164 helper
= __nf_conntrack_helper_find_byname("autofw");
168 help
= nfct_help(ct
);
169 help
->helper
= helper
;
171 /* alloc will set exp->master = ct */
172 exp
= nf_conntrack_expect_alloc(ct
);
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
;
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
);
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];
218 autofw_check(const char *tablename
,
220 const struct xt_target
*target
,
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
);
235 static struct xt_target autofw
= {
238 .target
= autofw_target
,
239 .targetsize
= sizeof(struct ip_autofw_info
),
241 .hooks
= 1 << NF_IP_PRE_ROUTING
,
242 .checkentry
= autofw_check
,
246 static int __init
ip_autofw_init(void)
250 ret
= nf_conntrack_helper_register(&autofw_helper
);
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
);