aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2005-04-24 21:41:38 -0400
committerDavid S. Miller <davem@davemloft.net>2005-04-24 21:41:38 -0400
commite281e3ac2b6c294d672034909883e7bb9e649ac7 (patch)
tree0a7a13aa6ecaddf030a8ec5deecce87ee424aae7 /net/ipv4
parent8e293ada7d6aaee43dd56a8077b83577dd108667 (diff)
[NETFILTER]: Fix NAT sequence number adjustment
The NAT changes in 2.6.11 changed the position where helpers are called and perform packet mangling. Before 2.6.11, a NAT helper was called before the packet was NATed and had its sequence number adjusted. Since 2.6.11, the helpers get packets with already adjusted sequence numbers. This breaks sequence number adjustment, adjust_tcp_sequence() needs the original sequence number to determine whether a packet was a retransmission and to store it for further corrections. It can't be reconstructed without more information than available, so this patch restores the old order by calling helpers from a new conntrack hook two priorities below ip_conntrack_confirm() and adjusting the sequence number from a new NAT hook one priority below ip_conntrack_confirm(). Tracked down by Phil Oester <kernel@linuxace.com> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c51
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c54
3 files changed, 98 insertions, 16 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 80a7bde2a57a..0c29ccf62a89 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -401,6 +401,16 @@ static unsigned int ip_confirm(unsigned int hooknum,
401 const struct net_device *out, 401 const struct net_device *out,
402 int (*okfn)(struct sk_buff *)) 402 int (*okfn)(struct sk_buff *))
403{ 403{
404 /* We've seen it coming out the other side: confirm it */
405 return ip_conntrack_confirm(pskb);
406}
407
408static unsigned int ip_conntrack_help(unsigned int hooknum,
409 struct sk_buff **pskb,
410 const struct net_device *in,
411 const struct net_device *out,
412 int (*okfn)(struct sk_buff *))
413{
404 struct ip_conntrack *ct; 414 struct ip_conntrack *ct;
405 enum ip_conntrack_info ctinfo; 415 enum ip_conntrack_info ctinfo;
406 416
@@ -412,9 +422,7 @@ static unsigned int ip_confirm(unsigned int hooknum,
412 if (ret != NF_ACCEPT) 422 if (ret != NF_ACCEPT)
413 return ret; 423 return ret;
414 } 424 }
415 425 return NF_ACCEPT;
416 /* We've seen it coming out the other side: confirm it */
417 return ip_conntrack_confirm(pskb);
418} 426}
419 427
420static unsigned int ip_conntrack_defrag(unsigned int hooknum, 428static unsigned int ip_conntrack_defrag(unsigned int hooknum,
@@ -516,13 +524,30 @@ static struct nf_hook_ops ip_conntrack_local_out_ops = {
516 .priority = NF_IP_PRI_CONNTRACK, 524 .priority = NF_IP_PRI_CONNTRACK,
517}; 525};
518 526
527/* helpers */
528static struct nf_hook_ops ip_conntrack_helper_out_ops = {
529 .hook = ip_conntrack_help,
530 .owner = THIS_MODULE,
531 .pf = PF_INET,
532 .hooknum = NF_IP_POST_ROUTING,
533 .priority = NF_IP_PRI_CONNTRACK_HELPER,
534};
535
536static struct nf_hook_ops ip_conntrack_helper_in_ops = {
537 .hook = ip_conntrack_help,
538 .owner = THIS_MODULE,
539 .pf = PF_INET,
540 .hooknum = NF_IP_LOCAL_IN,
541 .priority = NF_IP_PRI_CONNTRACK_HELPER,
542};
543
519/* Refragmenter; last chance. */ 544/* Refragmenter; last chance. */
520static struct nf_hook_ops ip_conntrack_out_ops = { 545static struct nf_hook_ops ip_conntrack_out_ops = {
521 .hook = ip_refrag, 546 .hook = ip_refrag,
522 .owner = THIS_MODULE, 547 .owner = THIS_MODULE,
523 .pf = PF_INET, 548 .pf = PF_INET,
524 .hooknum = NF_IP_POST_ROUTING, 549 .hooknum = NF_IP_POST_ROUTING,
525 .priority = NF_IP_PRI_LAST, 550 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
526}; 551};
527 552
528static struct nf_hook_ops ip_conntrack_local_in_ops = { 553static struct nf_hook_ops ip_conntrack_local_in_ops = {
@@ -530,7 +555,7 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = {
530 .owner = THIS_MODULE, 555 .owner = THIS_MODULE,
531 .pf = PF_INET, 556 .pf = PF_INET,
532 .hooknum = NF_IP_LOCAL_IN, 557 .hooknum = NF_IP_LOCAL_IN,
533 .priority = NF_IP_PRI_LAST-1, 558 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
534}; 559};
535 560
536/* Sysctl support */ 561/* Sysctl support */
@@ -831,10 +856,20 @@ static int init_or_cleanup(int init)
831 printk("ip_conntrack: can't register local out hook.\n"); 856 printk("ip_conntrack: can't register local out hook.\n");
832 goto cleanup_inops; 857 goto cleanup_inops;
833 } 858 }
859 ret = nf_register_hook(&ip_conntrack_helper_in_ops);
860 if (ret < 0) {
861 printk("ip_conntrack: can't register local in helper hook.\n");
862 goto cleanup_inandlocalops;
863 }
864 ret = nf_register_hook(&ip_conntrack_helper_out_ops);
865 if (ret < 0) {
866 printk("ip_conntrack: can't register postrouting helper hook.\n");
867 goto cleanup_helperinops;
868 }
834 ret = nf_register_hook(&ip_conntrack_out_ops); 869 ret = nf_register_hook(&ip_conntrack_out_ops);
835 if (ret < 0) { 870 if (ret < 0) {
836 printk("ip_conntrack: can't register post-routing hook.\n"); 871 printk("ip_conntrack: can't register post-routing hook.\n");
837 goto cleanup_inandlocalops; 872 goto cleanup_helperoutops;
838 } 873 }
839 ret = nf_register_hook(&ip_conntrack_local_in_ops); 874 ret = nf_register_hook(&ip_conntrack_local_in_ops);
840 if (ret < 0) { 875 if (ret < 0) {
@@ -860,6 +895,10 @@ static int init_or_cleanup(int init)
860 nf_unregister_hook(&ip_conntrack_local_in_ops); 895 nf_unregister_hook(&ip_conntrack_local_in_ops);
861 cleanup_inoutandlocalops: 896 cleanup_inoutandlocalops:
862 nf_unregister_hook(&ip_conntrack_out_ops); 897 nf_unregister_hook(&ip_conntrack_out_ops);
898 cleanup_helperoutops:
899 nf_unregister_hook(&ip_conntrack_helper_out_ops);
900 cleanup_helperinops:
901 nf_unregister_hook(&ip_conntrack_helper_in_ops);
863 cleanup_inandlocalops: 902 cleanup_inandlocalops:
864 nf_unregister_hook(&ip_conntrack_local_out_ops); 903 nf_unregister_hook(&ip_conntrack_local_out_ops);
865 cleanup_inops: 904 cleanup_inops:
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 162ceacfc29a..9fc6f93af0dd 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -356,15 +356,6 @@ unsigned int nat_packet(struct ip_conntrack *ct,
356 unsigned long statusbit; 356 unsigned long statusbit;
357 enum ip_nat_manip_type mtype = HOOK2MANIP(hooknum); 357 enum ip_nat_manip_type mtype = HOOK2MANIP(hooknum);
358 358
359 if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)
360 && (hooknum == NF_IP_POST_ROUTING || hooknum == NF_IP_LOCAL_IN)) {
361 DEBUGP("ip_nat_core: adjusting sequence number\n");
362 /* future: put this in a l4-proto specific function,
363 * and call this function here. */
364 if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
365 return NF_DROP;
366 }
367
368 if (mtype == IP_NAT_MANIP_SRC) 359 if (mtype == IP_NAT_MANIP_SRC)
369 statusbit = IPS_SRC_NAT; 360 statusbit = IPS_SRC_NAT;
370 else 361 else
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index dec4a74212cd..79f56f662b33 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -230,6 +230,25 @@ ip_nat_local_fn(unsigned int hooknum,
230 return ret; 230 return ret;
231} 231}
232 232
233static unsigned int
234ip_nat_adjust(unsigned int hooknum,
235 struct sk_buff **pskb,
236 const struct net_device *in,
237 const struct net_device *out,
238 int (*okfn)(struct sk_buff *))
239{
240 struct ip_conntrack *ct;
241 enum ip_conntrack_info ctinfo;
242
243 ct = ip_conntrack_get(*pskb, &ctinfo);
244 if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
245 DEBUGP("ip_nat_standalone: adjusting sequence number\n");
246 if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
247 return NF_DROP;
248 }
249 return NF_ACCEPT;
250}
251
233/* We must be after connection tracking and before packet filtering. */ 252/* We must be after connection tracking and before packet filtering. */
234 253
235/* Before packet filtering, change destination */ 254/* Before packet filtering, change destination */
@@ -250,6 +269,15 @@ static struct nf_hook_ops ip_nat_out_ops = {
250 .priority = NF_IP_PRI_NAT_SRC, 269 .priority = NF_IP_PRI_NAT_SRC,
251}; 270};
252 271
272/* After conntrack, adjust sequence number */
273static struct nf_hook_ops ip_nat_adjust_out_ops = {
274 .hook = ip_nat_adjust,
275 .owner = THIS_MODULE,
276 .pf = PF_INET,
277 .hooknum = NF_IP_POST_ROUTING,
278 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
279};
280
253/* Before packet filtering, change destination */ 281/* Before packet filtering, change destination */
254static struct nf_hook_ops ip_nat_local_out_ops = { 282static struct nf_hook_ops ip_nat_local_out_ops = {
255 .hook = ip_nat_local_fn, 283 .hook = ip_nat_local_fn,
@@ -268,6 +296,16 @@ static struct nf_hook_ops ip_nat_local_in_ops = {
268 .priority = NF_IP_PRI_NAT_SRC, 296 .priority = NF_IP_PRI_NAT_SRC,
269}; 297};
270 298
299/* After conntrack, adjust sequence number */
300static struct nf_hook_ops ip_nat_adjust_in_ops = {
301 .hook = ip_nat_adjust,
302 .owner = THIS_MODULE,
303 .pf = PF_INET,
304 .hooknum = NF_IP_LOCAL_IN,
305 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
306};
307
308
271static int init_or_cleanup(int init) 309static int init_or_cleanup(int init)
272{ 310{
273 int ret = 0; 311 int ret = 0;
@@ -296,10 +334,20 @@ static int init_or_cleanup(int init)
296 printk("ip_nat_init: can't register out hook.\n"); 334 printk("ip_nat_init: can't register out hook.\n");
297 goto cleanup_inops; 335 goto cleanup_inops;
298 } 336 }
337 ret = nf_register_hook(&ip_nat_adjust_in_ops);
338 if (ret < 0) {
339 printk("ip_nat_init: can't register adjust in hook.\n");
340 goto cleanup_outops;
341 }
342 ret = nf_register_hook(&ip_nat_adjust_out_ops);
343 if (ret < 0) {
344 printk("ip_nat_init: can't register adjust out hook.\n");
345 goto cleanup_adjustin_ops;
346 }
299 ret = nf_register_hook(&ip_nat_local_out_ops); 347 ret = nf_register_hook(&ip_nat_local_out_ops);
300 if (ret < 0) { 348 if (ret < 0) {
301 printk("ip_nat_init: can't register local out hook.\n"); 349 printk("ip_nat_init: can't register local out hook.\n");
302 goto cleanup_outops; 350 goto cleanup_adjustout_ops;;
303 } 351 }
304 ret = nf_register_hook(&ip_nat_local_in_ops); 352 ret = nf_register_hook(&ip_nat_local_in_ops);
305 if (ret < 0) { 353 if (ret < 0) {
@@ -312,6 +360,10 @@ static int init_or_cleanup(int init)
312 nf_unregister_hook(&ip_nat_local_in_ops); 360 nf_unregister_hook(&ip_nat_local_in_ops);
313 cleanup_localoutops: 361 cleanup_localoutops:
314 nf_unregister_hook(&ip_nat_local_out_ops); 362 nf_unregister_hook(&ip_nat_local_out_ops);
363 cleanup_adjustout_ops:
364 nf_unregister_hook(&ip_nat_adjust_out_ops);
365 cleanup_adjustin_ops:
366 nf_unregister_hook(&ip_nat_adjust_in_ops);
315 cleanup_outops: 367 cleanup_outops:
316 nf_unregister_hook(&ip_nat_out_ops); 368 nf_unregister_hook(&ip_nat_out_ops);
317 cleanup_inops: 369 cleanup_inops: