NETFILTER: remove unnecessary goto statement for error recovery
[tomato.git] / release / src-rt / linux / linux-2.6 / net / ipv4 / netfilter / bcm_nat.c
bloba95342a1fc43916688d35ea910bb8cd8f07e205f
1 /*
2 * Packet matching code.
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
7 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
8 * - increase module usage count as soon as we have rules inside
9 * a table
11 #include <linux/config.h>
12 #include <linux/cache.h>
13 #include <linux/skbuff.h>
14 #include <linux/kmod.h>
15 #include <linux/vmalloc.h>
16 #include <linux/netdevice.h>
17 #include <linux/module.h>
18 #include <linux/ip.h>
19 #include <net/route.h>
20 #include <net/ip.h>
21 #include <linux/netfilter.h>
22 #include <linux/netfilter_ipv4.h>
23 #include <net/netfilter/nf_nat_core.h>
24 #include <net/netfilter/nf_conntrack.h>
25 #include <net/netfilter/nf_conntrack_core.h>
26 #include <linux/netfilter/nf_conntrack_common.h>
27 #include <linux/netfilter_ipv4/ip_tables.h>
28 #ifdef HNDCTF
29 #include <typedefs.h>
30 extern bool ip_conntrack_is_ipc_allowed(struct sk_buff *skb, u_int32_t hooknum);
31 extern void ip_conntrack_ipct_add(struct sk_buff *skb, u_int32_t hooknum,
32 struct nf_conn *ct, enum ip_conntrack_info ci,
33 struct nf_conntrack_tuple *manip);
34 #endif /* HNDCTF */
37 #define DEBUGP(format, args...)
39 typedef int (*bcmNatHitHook)(struct sk_buff *skb);
40 typedef int (*bcmNatBindHook)(struct nf_conn *ct,enum ip_conntrack_info ctinfo,
41 unsigned int hooknum, struct sk_buff *skb);
43 extern bcmNatBindHook bcm_nat_bind_hook;
44 extern bcmNatHitHook bcm_nat_hit_hook;
46 static inline int
47 bcm_nat_bind_hook_func(bcmNatBindHook hook_func)
49 bcm_nat_bind_hook = hook_func;
50 return 1;
53 static inline int
54 bcm_nat_hit_hook_func(bcmNatHitHook hook_func)
56 bcm_nat_hit_hook = hook_func;
57 return 1;
60 extern int bcm_manip_pkt(u_int16_t proto,
61 struct sk_buff *skb,
62 unsigned int iphdroff,
63 const struct nf_conntrack_tuple *target,
64 enum nf_nat_manip_type maniptype);
66 extern int bcm_nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
67 const struct nf_conntrack_tuple *orig,
68 const struct nf_conntrack_l3proto *l3proto,
69 const struct nf_conntrack_l4proto *l4proto);
71 /*
72 * Send packets to output.
74 static inline int bcm_fast_path_output(struct sk_buff *skb)
76 int ret = 0;
77 struct dst_entry *dst = skb->dst;
78 struct hh_cache *hh = dst->hh;
80 if (hh) {
81 unsigned seq;
82 int hh_len;
84 do {
85 int hh_alen;
86 seq = read_seqbegin(&hh->hh_lock);
87 hh_len = hh->hh_len;
88 hh_alen = HH_DATA_ALIGN(hh_len);
89 memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
90 } while (read_seqretry(&hh->hh_lock, seq));
92 skb_push(skb, hh_len);
93 ret = hh->hh_output(skb);
94 if (ret==1)
95 return 0; /* Don't return 1 */
96 } else if (dst->neighbour) {
97 ret = dst->neighbour->output(skb);
98 if (ret==1)
99 return 0; /* Don't return 1 */
101 return ret;
104 static inline int ip_skb_dst_mtu(struct sk_buff *skb)
106 struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL;
108 return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ?
109 skb->dst->dev->mtu : dst_mtu(skb->dst);
112 static int bcm_fast_path(struct sk_buff *skb)
114 if (skb->dst == NULL) {
115 struct iphdr *iph = ip_hdr(skb);
116 struct net_device *dev = skb->dev;
118 if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev)) {
119 return NF_DROP;
121 /* Change skb owner to output device */
122 skb->dev = skb->dst->dev;
125 if (skb->dst) {
126 if (skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb))
127 return ip_fragment(skb, bcm_fast_path_output);
128 else
129 return bcm_fast_path_output(skb);
132 kfree_skb(skb);
133 return -EINVAL;
136 static int
137 bcm_do_bindings(struct nf_conn *ct,
138 enum ip_conntrack_info ctinfo,
139 struct sk_buff *skb,
140 struct nf_conntrack_l3proto *l3proto,
141 struct nf_conntrack_l4proto *l4proto)
143 struct iphdr *iph = ip_hdr(skb);
144 unsigned int i;
145 static int hn[2] = {NF_IP_PRE_ROUTING, NF_IP_POST_ROUTING};
146 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
147 #ifdef HNDCTF
148 bool enabled = ip_conntrack_is_ipc_allowed(skb, NF_IP_PRE_ROUTING);
149 #endif /* HNDCTF */
151 for (i = 0; i < 2; i++) {
152 enum nf_nat_manip_type mtype = HOOK2MANIP(hn[i]);
153 unsigned long statusbit;
155 if (mtype == IP_NAT_MANIP_SRC)
156 statusbit = IPS_SRC_NAT;
157 else
158 statusbit = IPS_DST_NAT;
160 /* Invert if this is reply dir. */
161 if (dir == IP_CT_DIR_REPLY)
162 statusbit ^= IPS_NAT_MASK;
164 if (ct->status & statusbit) {
165 struct nf_conntrack_tuple target;
167 if (!skb_make_writable(skb, 0))
168 return NF_DROP;
170 if (skb->dst == NULL && mtype == IP_NAT_MANIP_SRC) {
171 struct net_device *dev = skb->dev;
172 if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))
173 return NF_DROP;
174 /* Change skb owner */
175 skb->dev = skb->dst->dev;
178 /* We are aiming to look like inverse of other direction. */
179 bcm_nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple, l3proto, l4proto);
180 #ifdef HNDCTF
181 if (enabled)
182 ip_conntrack_ipct_add(skb, hn[i], ct, ctinfo, &target);
183 #endif /* HNDCTF */
184 if (!bcm_manip_pkt(target.dst.protonum, skb, 0, &target, mtype))
185 return NF_DROP;
189 return NF_FAST_NAT;
192 static int __init bcm_nat_init(void)
194 bcm_nat_hit_hook_func (bcm_fast_path);
195 bcm_nat_bind_hook_func ((bcmNatBindHook)bcm_do_bindings);
196 printk("BCM fast NAT: INIT\n");
197 return 0;
200 static void __exit bcm_nat_fini(void)
202 bcm_nat_hit_hook_func (NULL);
203 bcm_nat_bind_hook_func (NULL);
206 module_init(bcm_nat_init);
207 module_exit(bcm_nat_fini);
208 MODULE_LICENSE("Proprietary");