1
Patch found at http://patchwork.netfilter.org/netfilter-devel/patch.pl?id=2663
2
Thank to Roberto Nibali for his work
4
diff -Nur linux-2.4.31-orig/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.31-pab2/include/linux/netfilter_ipv4/ip_conntrack.h
5
--- linux-2.4.31-orig/include/linux/netfilter_ipv4/ip_conntrack.h 2005-04-04 03:42:20 +0200
6
+++ linux-2.4.31-pab2/include/linux/netfilter_ipv4/ip_conntrack.h 2005-06-29 12:23:37 +0200
8
/* Call me when a conntrack is destroyed. */
9
extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
11
+/* Fake conntrack entry for untracked connections */
12
+extern struct ip_conntrack ip_conntrack_untracked;
14
/* Returns new sk_buff, or NULL */
16
ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
17
diff -Nur linux-2.4.31-orig/include/linux/netfilter_ipv4/ipt_conntrack.h linux-2.4.31-pab2/include/linux/netfilter_ipv4/ipt_conntrack.h
18
--- linux-2.4.31-orig/include/linux/netfilter_ipv4/ipt_conntrack.h 2002-11-29 00:53:15 +0100
19
+++ linux-2.4.31-pab2/include/linux/netfilter_ipv4/ipt_conntrack.h 2005-06-29 12:23:37 +0200
22
#define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
23
#define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
24
+#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
26
/* flags, invflags: */
27
#define IPT_CONNTRACK_STATE 0x01
28
diff -Nur linux-2.4.31-orig/include/linux/netfilter_ipv4/ipt_state.h linux-2.4.31-pab2/include/linux/netfilter_ipv4/ipt_state.h
29
--- linux-2.4.31-orig/include/linux/netfilter_ipv4/ipt_state.h 2000-04-14 18:37:20 +0200
30
+++ linux-2.4.31-pab2/include/linux/netfilter_ipv4/ipt_state.h 2005-06-29 12:23:37 +0200
33
#define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
34
#define IPT_STATE_INVALID (1 << 0)
35
+#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
39
diff -Nur linux-2.4.31-orig/include/linux/netfilter_ipv4.h linux-2.4.31-pab2/include/linux/netfilter_ipv4.h
40
--- linux-2.4.31-orig/include/linux/netfilter_ipv4.h 2002-02-25 20:38:13 +0100
41
+++ linux-2.4.31-pab2/include/linux/netfilter_ipv4.h 2005-06-29 12:23:37 +0200
44
enum nf_ip_hook_priorities {
45
NF_IP_PRI_FIRST = INT_MIN,
46
+ NF_IP_PRI_CONNTRACK_DEFRAG = -400,
47
+ NF_IP_PRI_RAW = -300,
48
NF_IP_PRI_CONNTRACK = -200,
49
NF_IP_PRI_MANGLE = -150,
50
NF_IP_PRI_NAT_DST = -100,
51
diff -Nur linux-2.4.31-orig/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.31-pab2/net/ipv4/netfilter/ip_conntrack_core.c
52
--- linux-2.4.31-orig/net/ipv4/netfilter/ip_conntrack_core.c 2005-04-04 03:42:20 +0200
53
+++ linux-2.4.31-pab2/net/ipv4/netfilter/ip_conntrack_core.c 2005-06-29 12:42:09 +0200
55
struct list_head *ip_conntrack_hash;
56
static kmem_cache_t *ip_conntrack_cachep;
57
static LIST_HEAD(unconfirmed);
58
+struct ip_conntrack ip_conntrack_untracked;
60
extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
66
+ /* Previously seen (loopback or untracked)? Ignore. */
71
+ if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
72
+ if (net_ratelimit()) {
73
+ printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
74
+ (*pskb)->nh.iph->protocol, hooknum);
79
/* FIXME: Do this right please. --RR */
80
(*pskb)->nfcache |= NFC_UNKNOWN;
86
- /* Previously seen (loopback)? Ignore. Do this before
91
- /* Gather fragments. */
92
- if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
93
- *pskb = ip_ct_gather_frags(*pskb,
94
- hooknum == NF_IP_PRE_ROUTING ?
95
- IP_DEFRAG_CONNTRACK_IN :
96
- IP_DEFRAG_CONNTRACK_OUT);
101
proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
103
/* It may be an icmp error... */
104
@@ -1392,6 +1391,8 @@
106
goto i_see_dead_people;
108
+ while (atomic_read(&ip_conntrack_untracked.ct_general.use) > 1)
111
kmem_cache_destroy(ip_conntrack_cachep);
112
vfree(ip_conntrack_hash);
113
@@ -1459,6 +1460,18 @@
115
/* For use by ipt_REJECT */
116
ip_ct_attach = ip_conntrack_attach;
118
+ /* Set up fake conntrack:
119
+ - never to be deleted, not in any hashes */
120
+ atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
121
+ /* - and let it look as if it's a confirmed connection */
122
+ set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
123
+ /* - and prepare the ctinfo field for REJECT/NAT. */
124
+ ip_conntrack_untracked.infos[IP_CT_NEW].master =
125
+ ip_conntrack_untracked.infos[IP_CT_RELATED].master =
126
+ ip_conntrack_untracked.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master =
127
+ &ip_conntrack_untracked.ct_general;
132
diff -Nur linux-2.4.31-orig/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.31-pab2/net/ipv4/netfilter/ip_conntrack_standalone.c
133
--- linux-2.4.31-orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-04-04 03:42:20 +0200
134
+++ linux-2.4.31-pab2/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-06-29 12:23:37 +0200
136
return ip_conntrack_confirm(*pskb);
139
+static unsigned int ip_conntrack_defrag(unsigned int hooknum,
140
+ struct sk_buff **pskb,
141
+ const struct net_device *in,
142
+ const struct net_device *out,
143
+ int (*okfn)(struct sk_buff *))
145
+ /* Previously seen (loopback)? Ignore. Do this before
146
+ * fragment check. */
150
+ /* Gather fragments. */
151
+ if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
152
+ *pskb = ip_ct_gather_frags(*pskb,
153
+ hooknum == NF_IP_PRE_ROUTING ?
154
+ IP_DEFRAG_CONNTRACK_IN :
155
+ IP_DEFRAG_CONNTRACK_OUT);
162
static unsigned int ip_refrag(unsigned int hooknum,
163
struct sk_buff **pskb,
164
const struct net_device *in,
167
/* Connection tracking may drop packets, but never alters them, so
168
make it the first hook. */
169
+static struct nf_hook_ops ip_conntrack_defrag_ops
170
+= { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_PRE_ROUTING,
171
+ NF_IP_PRI_CONNTRACK_DEFRAG };
172
static struct nf_hook_ops ip_conntrack_in_ops
173
= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
174
NF_IP_PRI_CONNTRACK };
175
+static struct nf_hook_ops ip_conntrack_defrag_local_out_ops
176
+= { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_LOCAL_OUT,
177
+ NF_IP_PRI_CONNTRACK_DEFRAG };
178
static struct nf_hook_ops ip_conntrack_local_out_ops
179
= { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
180
NF_IP_PRI_CONNTRACK };
181
@@ -353,10 +382,21 @@
182
if (!proc) goto cleanup_init;
183
proc->owner = THIS_MODULE;
185
+ ret = nf_register_hook(&ip_conntrack_defrag_ops);
187
+ printk("ip_conntrack: can't register pre-routing defrag hook.\n");
190
+ ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
192
+ printk("ip_conntrack: can't register local_out defrag hook.\n");
193
+ goto cleanup_defragops;
196
ret = nf_register_hook(&ip_conntrack_in_ops);
198
printk("ip_conntrack: can't register pre-routing hook.\n");
200
+ goto cleanup_defraglocalops;
202
ret = nf_register_hook(&ip_conntrack_local_out_ops);
205
nf_unregister_hook(&ip_conntrack_local_out_ops);
207
nf_unregister_hook(&ip_conntrack_in_ops);
208
+ cleanup_defraglocalops:
209
+ nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
211
+ nf_unregister_hook(&ip_conntrack_defrag_ops);
213
proc_net_remove("ip_conntrack");
216
EXPORT_SYMBOL(ip_conntrack_expect_list);
217
EXPORT_SYMBOL(ip_conntrack_lock);
218
EXPORT_SYMBOL(ip_conntrack_hash);
219
+EXPORT_SYMBOL(ip_conntrack_untracked);
220
EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
221
EXPORT_SYMBOL_GPL(ip_conntrack_put);
222
diff -Nur linux-2.4.31-orig/net/ipv4/netfilter/ip_nat_core.c linux-2.4.31-pab2/net/ipv4/netfilter/ip_nat_core.c
223
--- linux-2.4.31-orig/net/ipv4/netfilter/ip_nat_core.c 2005-04-04 03:42:20 +0200
224
+++ linux-2.4.31-pab2/net/ipv4/netfilter/ip_nat_core.c 2005-06-29 12:23:37 +0200
225
@@ -1024,6 +1024,10 @@
226
IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
227
ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
229
+ /* Initialize fake conntrack so that NAT will skip it */
230
+ ip_conntrack_untracked.nat.info.initialized |=
231
+ (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
236
diff -Nur linux-2.4.31-orig/net/ipv4/netfilter/ipt_conntrack.c linux-2.4.31-pab2/net/ipv4/netfilter/ipt_conntrack.c
237
--- linux-2.4.31-orig/net/ipv4/netfilter/ipt_conntrack.c 2004-02-18 14:36:32 +0100
238
+++ linux-2.4.31-pab2/net/ipv4/netfilter/ipt_conntrack.c 2005-06-29 12:23:37 +0200
241
#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
244
+ if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
245
+ statebit = IPT_CONNTRACK_STATE_UNTRACKED;
247
statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
249
statebit = IPT_CONNTRACK_STATE_INVALID;
250
diff -Nur linux-2.4.31-orig/net/ipv4/netfilter/ipt_state.c linux-2.4.31-pab2/net/ipv4/netfilter/ipt_state.c
251
--- linux-2.4.31-orig/net/ipv4/netfilter/ipt_state.c 2004-02-18 14:36:32 +0100
252
+++ linux-2.4.31-pab2/net/ipv4/netfilter/ipt_state.c 2005-06-29 12:23:37 +0200
254
enum ip_conntrack_info ctinfo;
255
unsigned int statebit;
257
- if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
258
+ if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
259
+ statebit = IPT_STATE_UNTRACKED;
260
+ else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
261
statebit = IPT_STATE_INVALID;
263
statebit = IPT_STATE_BIT(ctinfo);