diff options
author | Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> | 2007-07-08 01:24:28 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:17:20 -0400 |
commit | 2d59e5ca8c7113ad91452f0f9259a4b55ee90323 (patch) | |
tree | 16ffd5284bb5462eaa3af285977389afefca54ca /net/ipv4 | |
parent | e54cbc1f91dea4f98b6209e693d3b5eae46321bd (diff) |
[NETFILTER]: nf_nat: use extension infrastructure
Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
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/nf_conntrack_l3proto_ipv4.c | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 60 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_standalone.c | 21 |
3 files changed, 65 insertions, 19 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 6dc72a815f77..96f641d07a40 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -108,9 +108,6 @@ EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded); | |||
108 | 108 | ||
109 | static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) | 109 | static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) |
110 | { | 110 | { |
111 | if (nf_nat_module_is_loaded) | ||
112 | return NF_CT_F_NAT; | ||
113 | |||
114 | return NF_CT_F_BASIC; | 111 | return NF_CT_F_BASIC; |
115 | } | 112 | } |
116 | 113 | ||
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index ac7e8abbbdeb..4ce82d7014ff 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -297,11 +297,21 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
297 | unsigned int hooknum) | 297 | unsigned int hooknum) |
298 | { | 298 | { |
299 | struct nf_conntrack_tuple curr_tuple, new_tuple; | 299 | struct nf_conntrack_tuple curr_tuple, new_tuple; |
300 | struct nf_conn_nat *nat = nfct_nat(ct); | 300 | struct nf_conn_nat *nat; |
301 | struct nf_nat_info *info = &nat->info; | 301 | struct nf_nat_info *info; |
302 | int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK); | 302 | int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK); |
303 | enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); | 303 | enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); |
304 | 304 | ||
305 | /* nat helper or nfctnetlink also setup binding */ | ||
306 | nat = nfct_nat(ct); | ||
307 | if (!nat) { | ||
308 | nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); | ||
309 | if (nat == NULL) { | ||
310 | DEBUGP("failed to add NAT extension\n"); | ||
311 | return NF_ACCEPT; | ||
312 | } | ||
313 | } | ||
314 | |||
305 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || | 315 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || |
306 | hooknum == NF_IP_POST_ROUTING || | 316 | hooknum == NF_IP_POST_ROUTING || |
307 | hooknum == NF_IP_LOCAL_IN || | 317 | hooknum == NF_IP_LOCAL_IN || |
@@ -338,6 +348,8 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
338 | 348 | ||
339 | srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 349 | srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
340 | write_lock_bh(&nf_nat_lock); | 350 | write_lock_bh(&nf_nat_lock); |
351 | /* nf_conntrack_alter_reply might re-allocate exntension aera */ | ||
352 | info = &nfct_nat(ct)->info; | ||
341 | info->ct = ct; | 353 | info->ct = ct; |
342 | list_add(&info->bysource, &bysource[srchash]); | 354 | list_add(&info->bysource, &bysource[srchash]); |
343 | write_unlock_bh(&nf_nat_lock); | 355 | write_unlock_bh(&nf_nat_lock); |
@@ -592,17 +604,52 @@ nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range) | |||
592 | EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr); | 604 | EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr); |
593 | #endif | 605 | #endif |
594 | 606 | ||
607 | static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) | ||
608 | { | ||
609 | struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT); | ||
610 | struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old; | ||
611 | struct nf_conn *ct = old_nat->info.ct; | ||
612 | unsigned int srchash; | ||
613 | |||
614 | if (!(ct->status & IPS_NAT_DONE_MASK)) | ||
615 | return; | ||
616 | |||
617 | srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | ||
618 | |||
619 | write_lock_bh(&nf_nat_lock); | ||
620 | list_replace(&old_nat->info.bysource, &new_nat->info.bysource); | ||
621 | new_nat->info.ct = ct; | ||
622 | write_unlock_bh(&nf_nat_lock); | ||
623 | } | ||
624 | |||
625 | struct nf_ct_ext_type nat_extend = { | ||
626 | .len = sizeof(struct nf_conn_nat), | ||
627 | .align = __alignof__(struct nf_conn_nat), | ||
628 | .move = nf_nat_move_storage, | ||
629 | .id = NF_CT_EXT_NAT, | ||
630 | .flags = NF_CT_EXT_F_PREALLOC, | ||
631 | }; | ||
632 | |||
595 | static int __init nf_nat_init(void) | 633 | static int __init nf_nat_init(void) |
596 | { | 634 | { |
597 | size_t i; | 635 | size_t i; |
636 | int ret; | ||
637 | |||
638 | ret = nf_ct_extend_register(&nat_extend); | ||
639 | if (ret < 0) { | ||
640 | printk(KERN_ERR "nf_nat_core: Unable to register extension\n"); | ||
641 | return ret; | ||
642 | } | ||
598 | 643 | ||
599 | /* Leave them the same for the moment. */ | 644 | /* Leave them the same for the moment. */ |
600 | nf_nat_htable_size = nf_conntrack_htable_size; | 645 | nf_nat_htable_size = nf_conntrack_htable_size; |
601 | 646 | ||
602 | /* One vmalloc for both hash tables */ | 647 | /* One vmalloc for both hash tables */ |
603 | bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size); | 648 | bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size); |
604 | if (!bysource) | 649 | if (!bysource) { |
605 | return -ENOMEM; | 650 | ret = -ENOMEM; |
651 | goto cleanup_extend; | ||
652 | } | ||
606 | 653 | ||
607 | /* Sew in builtin protocols. */ | 654 | /* Sew in builtin protocols. */ |
608 | write_lock_bh(&nf_nat_lock); | 655 | write_lock_bh(&nf_nat_lock); |
@@ -626,6 +673,10 @@ static int __init nf_nat_init(void) | |||
626 | 673 | ||
627 | l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); | 674 | l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); |
628 | return 0; | 675 | return 0; |
676 | |||
677 | cleanup_extend: | ||
678 | nf_ct_extend_unregister(&nat_extend); | ||
679 | return ret; | ||
629 | } | 680 | } |
630 | 681 | ||
631 | /* Clear NAT section of all conntracks, in case we're loaded again. */ | 682 | /* Clear NAT section of all conntracks, in case we're loaded again. */ |
@@ -647,6 +698,7 @@ static void __exit nf_nat_cleanup(void) | |||
647 | synchronize_rcu(); | 698 | synchronize_rcu(); |
648 | vfree(bysource); | 699 | vfree(bysource); |
649 | nf_ct_l3proto_put(l3proto); | 700 | nf_ct_l3proto_put(l3proto); |
701 | nf_ct_extend_unregister(&nat_extend); | ||
650 | } | 702 | } |
651 | 703 | ||
652 | MODULE_LICENSE("GPL"); | 704 | MODULE_LICENSE("GPL"); |
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 0b2f0c33f7cd..51a2708f7bf0 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <net/netfilter/nf_conntrack.h> | 20 | #include <net/netfilter/nf_conntrack.h> |
21 | #include <net/netfilter/nf_conntrack_core.h> | 21 | #include <net/netfilter/nf_conntrack_core.h> |
22 | #include <net/netfilter/nf_conntrack_extend.h> | ||
22 | #include <net/netfilter/nf_nat.h> | 23 | #include <net/netfilter/nf_nat.h> |
23 | #include <net/netfilter/nf_nat_rule.h> | 24 | #include <net/netfilter/nf_nat_rule.h> |
24 | #include <net/netfilter/nf_nat_protocol.h> | 25 | #include <net/netfilter/nf_nat_protocol.h> |
@@ -113,8 +114,13 @@ nf_nat_fn(unsigned int hooknum, | |||
113 | return NF_ACCEPT; | 114 | return NF_ACCEPT; |
114 | 115 | ||
115 | nat = nfct_nat(ct); | 116 | nat = nfct_nat(ct); |
116 | if (!nat) | 117 | if (!nat) { |
117 | return NF_ACCEPT; | 118 | nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); |
119 | if (nat == NULL) { | ||
120 | DEBUGP("failed to add NAT extension\n"); | ||
121 | return NF_ACCEPT; | ||
122 | } | ||
123 | } | ||
118 | 124 | ||
119 | switch (ctinfo) { | 125 | switch (ctinfo) { |
120 | case IP_CT_RELATED: | 126 | case IP_CT_RELATED: |
@@ -326,18 +332,10 @@ static struct nf_hook_ops nf_nat_ops[] = { | |||
326 | 332 | ||
327 | static int __init nf_nat_standalone_init(void) | 333 | static int __init nf_nat_standalone_init(void) |
328 | { | 334 | { |
329 | int size, ret = 0; | 335 | int ret = 0; |
330 | 336 | ||
331 | need_conntrack(); | 337 | need_conntrack(); |
332 | 338 | ||
333 | size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) + | ||
334 | sizeof(struct nf_conn_nat); | ||
335 | ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size); | ||
336 | if (ret < 0) { | ||
337 | printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n"); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | #ifdef CONFIG_XFRM | 339 | #ifdef CONFIG_XFRM |
342 | BUG_ON(ip_nat_decode_session != NULL); | 340 | BUG_ON(ip_nat_decode_session != NULL); |
343 | ip_nat_decode_session = nat_decode_session; | 341 | ip_nat_decode_session = nat_decode_session; |
@@ -362,7 +360,6 @@ static int __init nf_nat_standalone_init(void) | |||
362 | ip_nat_decode_session = NULL; | 360 | ip_nat_decode_session = NULL; |
363 | synchronize_net(); | 361 | synchronize_net(); |
364 | #endif | 362 | #endif |
365 | nf_conntrack_unregister_cache(NF_CT_F_NAT); | ||
366 | return ret; | 363 | return ret; |
367 | } | 364 | } |
368 | 365 | ||