]>
Commit | Line | Data |
---|---|---|
cd1a2927 MT |
1 | Patch found at http://patchwork.netfilter.org/netfilter-devel/patch.pl?id=2663 |
2 | Thank to Roberto Nibali for his work | |
3 | ||
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 | |
7 | @@ -249,6 +249,9 @@ | |
8 | /* Call me when a conntrack is destroyed. */ | |
9 | extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack); | |
10 | ||
11 | +/* Fake conntrack entry for untracked connections */ | |
12 | +extern struct ip_conntrack ip_conntrack_untracked; | |
13 | + | |
14 | /* Returns new sk_buff, or NULL */ | |
15 | struct sk_buff * | |
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 | |
20 | @@ -10,6 +10,7 @@ | |
21 | ||
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)) | |
25 | ||
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 | |
31 | @@ -3,6 +3,7 @@ | |
32 | ||
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)) | |
36 | ||
37 | struct ipt_state_info | |
38 | { | |
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 | |
42 | @@ -51,6 +51,8 @@ | |
43 | ||
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 | |
54 | @@ -65,6 +65,7 @@ | |
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; | |
59 | ||
60 | extern struct ip_conntrack_protocol ip_conntrack_generic_protocol; | |
61 | ||
62 | @@ -823,6 +824,19 @@ | |
63 | int set_reply; | |
64 | int ret; | |
65 | ||
66 | + /* Previously seen (loopback or untracked)? Ignore. */ | |
67 | + if ((*pskb)->nfct) | |
68 | + return NF_ACCEPT; | |
69 | + | |
70 | + /* Never happen */ | |
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); | |
75 | + } | |
76 | + return NF_DROP; | |
77 | + } | |
78 | + | |
79 | /* FIXME: Do this right please. --RR */ | |
80 | (*pskb)->nfcache |= NFC_UNKNOWN; | |
81 | ||
82 | @@ -841,21 +855,6 @@ | |
83 | } | |
84 | #endif | |
85 | ||
86 | - /* Previously seen (loopback)? Ignore. Do this before | |
87 | - fragment check. */ | |
88 | - if ((*pskb)->nfct) | |
89 | - return NF_ACCEPT; | |
90 | - | |
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); | |
97 | - if (!*pskb) | |
98 | - return NF_STOLEN; | |
99 | - } | |
100 | - | |
101 | proto = ip_ct_find_proto((*pskb)->nh.iph->protocol); | |
102 | ||
103 | /* It may be an icmp error... */ | |
104 | @@ -1392,6 +1391,8 @@ | |
105 | schedule(); | |
106 | goto i_see_dead_people; | |
107 | } | |
108 | + while (atomic_read(&ip_conntrack_untracked.ct_general.use) > 1) | |
109 | + schedule(); | |
110 | ||
111 | kmem_cache_destroy(ip_conntrack_cachep); | |
112 | vfree(ip_conntrack_hash); | |
113 | @@ -1459,6 +1460,18 @@ | |
114 | ||
115 | /* For use by ipt_REJECT */ | |
116 | ip_ct_attach = ip_conntrack_attach; | |
117 | + | |
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; | |
128 | + | |
129 | return ret; | |
130 | ||
131 | err_free_hash: | |
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 | |
135 | @@ -189,6 +189,29 @@ | |
136 | return ip_conntrack_confirm(*pskb); | |
137 | } | |
138 | ||
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 *)) | |
144 | +{ | |
145 | + /* Previously seen (loopback)? Ignore. Do this before | |
146 | + * fragment check. */ | |
147 | + if ((*pskb)->nfct) | |
148 | + return NF_ACCEPT; | |
149 | + | |
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); | |
156 | + if (!*pskb) | |
157 | + return NF_STOLEN; | |
158 | + } | |
159 | + return NF_ACCEPT; | |
160 | +} | |
161 | + | |
162 | static unsigned int ip_refrag(unsigned int hooknum, | |
163 | struct sk_buff **pskb, | |
164 | const struct net_device *in, | |
165 | @@ -230,9 +253,15 @@ | |
166 | ||
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; | |
184 | ||
185 | + ret = nf_register_hook(&ip_conntrack_defrag_ops); | |
186 | + if (ret < 0) { | |
187 | + printk("ip_conntrack: can't register pre-routing defrag hook.\n"); | |
188 | + goto cleanup_proc; | |
189 | + } | |
190 | + ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops); | |
191 | + if (ret < 0) { | |
192 | + printk("ip_conntrack: can't register local_out defrag hook.\n"); | |
193 | + goto cleanup_defragops; | |
194 | + } | |
195 | + | |
196 | ret = nf_register_hook(&ip_conntrack_in_ops); | |
197 | if (ret < 0) { | |
198 | printk("ip_conntrack: can't register pre-routing hook.\n"); | |
199 | - goto cleanup_proc; | |
200 | + goto cleanup_defraglocalops; | |
201 | } | |
202 | ret = nf_register_hook(&ip_conntrack_local_out_ops); | |
203 | if (ret < 0) { | |
204 | @@ -394,6 +434,10 @@ | |
205 | nf_unregister_hook(&ip_conntrack_local_out_ops); | |
206 | cleanup_inops: | |
207 | nf_unregister_hook(&ip_conntrack_in_ops); | |
208 | + cleanup_defraglocalops: | |
209 | + nf_unregister_hook(&ip_conntrack_defrag_local_out_ops); | |
210 | + cleanup_defragops: | |
211 | + nf_unregister_hook(&ip_conntrack_defrag_ops); | |
212 | cleanup_proc: | |
213 | proc_net_remove("ip_conntrack"); | |
214 | cleanup_init: | |
215 | @@ -483,5 +527,6 @@ | |
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; | |
228 | ||
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); | |
232 | + | |
233 | return 0; | |
234 | } | |
235 | ||
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 | |
239 | @@ -27,7 +27,9 @@ | |
240 | ||
241 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) | |
242 | ||
243 | - if (ct) | |
244 | + if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW]) | |
245 | + statebit = IPT_CONNTRACK_STATE_UNTRACKED; | |
246 | + else if (ct) | |
247 | statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); | |
248 | else | |
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 | |
253 | @@ -21,7 +21,9 @@ | |
254 | enum ip_conntrack_info ctinfo; | |
255 | unsigned int statebit; | |
256 | ||
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; | |
262 | else | |
263 | statebit = IPT_STATE_BIT(ctinfo); |