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
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>
19 #include <net/route.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>
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
);
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
;
47 bcm_nat_bind_hook_func(bcmNatBindHook hook_func
)
49 bcm_nat_bind_hook
= hook_func
;
54 bcm_nat_hit_hook_func(bcmNatHitHook hook_func
)
56 bcm_nat_hit_hook
= hook_func
;
60 extern int bcm_manip_pkt(u_int16_t proto
,
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
);
72 * Send packets to output.
74 static inline int bcm_fast_path_output(struct sk_buff
*skb
)
77 struct dst_entry
*dst
= skb
->dst
;
78 struct hh_cache
*hh
= dst
->hh
;
86 seq
= read_seqbegin(&hh
->hh_lock
);
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
);
95 return 0; /* Don't return 1 */
96 } else if (dst
->neighbour
) {
97 ret
= dst
->neighbour
->output(skb
);
99 return 0; /* Don't return 1 */
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
)) {
121 /* Change skb owner to output device */
122 skb
->dev
= skb
->dst
->dev
;
126 if (skb
->len
> ip_skb_dst_mtu(skb
) && !skb_is_gso(skb
))
127 return ip_fragment(skb
, bcm_fast_path_output
);
129 return bcm_fast_path_output(skb
);
137 bcm_do_bindings(struct nf_conn
*ct
,
138 enum ip_conntrack_info ctinfo
,
140 struct nf_conntrack_l3proto
*l3proto
,
141 struct nf_conntrack_l4proto
*l4proto
)
143 struct iphdr
*iph
= ip_hdr(skb
);
145 static int hn
[2] = {NF_IP_PRE_ROUTING
, NF_IP_POST_ROUTING
};
146 enum ip_conntrack_dir dir
= CTINFO2DIR(ctinfo
);
148 bool enabled
= ip_conntrack_is_ipc_allowed(skb
, NF_IP_PRE_ROUTING
);
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
;
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))
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
))
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
);
182 ip_conntrack_ipct_add(skb
, hn
[i
], ct
, ctinfo
, &target
);
184 if (!bcm_manip_pkt(target
.dst
.protonum
, skb
, 0, &target
, mtype
))
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");
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");