diff options
-rw-r--r-- | include/linux/netfilter_ipv4.h | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_standalone.c | 51 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_core.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 54 |
4 files changed, 101 insertions, 16 deletions
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index c9bacf9b2431..9e5750079e09 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h | |||
@@ -62,6 +62,9 @@ enum nf_ip_hook_priorities { | |||
62 | NF_IP_PRI_FILTER = 0, | 62 | NF_IP_PRI_FILTER = 0, |
63 | NF_IP_PRI_NAT_SRC = 100, | 63 | NF_IP_PRI_NAT_SRC = 100, |
64 | NF_IP_PRI_SELINUX_LAST = 225, | 64 | NF_IP_PRI_SELINUX_LAST = 225, |
65 | NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2, | ||
66 | NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1, | ||
67 | NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, | ||
65 | NF_IP_PRI_LAST = INT_MAX, | 68 | NF_IP_PRI_LAST = INT_MAX, |
66 | }; | 69 | }; |
67 | 70 | ||
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 | |||
408 | static 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 | ||
420 | static unsigned int ip_conntrack_defrag(unsigned int hooknum, | 428 | static 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 */ | ||
528 | static 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 | |||
536 | static 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. */ |
520 | static struct nf_hook_ops ip_conntrack_out_ops = { | 545 | static 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 | ||
528 | static struct nf_hook_ops ip_conntrack_local_in_ops = { | 553 | static 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 | ||
233 | static unsigned int | ||
234 | ip_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 */ | ||
273 | static 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 */ |
254 | static struct nf_hook_ops ip_nat_local_out_ops = { | 282 | static 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 */ | ||
300 | static 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 | |||
271 | static int init_or_cleanup(int init) | 309 | static 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: |