diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2006-12-03 01:07:13 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-12-03 01:07:13 -0500 |
commit | 5b1158e909ecbe1a052203e0d8df15633f829930 (patch) | |
tree | 1d29320fd6184b982b1a8a83e7e1e9f25537d3ff /net/netfilter | |
parent | d2483ddefd38b06053cdce7206382ca61f6282b1 (diff) |
[NETFILTER]: Add NAT support for nf_conntrack
Add NAT support for nf_conntrack. Joint work of Jozsef Kadlecsik,
Yasuyuki Kozakai, Martin Josefsson and myself.
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 23 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 46 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_standalone.c | 5 |
4 files changed, 52 insertions, 24 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index f952a7fb6ae3..aa8beabfeebb 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -579,7 +579,8 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, | |||
579 | /* FIXME: protect helper list per RCU */ | 579 | /* FIXME: protect helper list per RCU */ |
580 | read_lock_bh(&nf_conntrack_lock); | 580 | read_lock_bh(&nf_conntrack_lock); |
581 | helper = __nf_ct_helper_find(repl); | 581 | helper = __nf_ct_helper_find(repl); |
582 | if (helper) | 582 | /* NAT might want to assign a helper later */ |
583 | if (helper || features & NF_CT_F_NAT) | ||
583 | features |= NF_CT_F_HELP; | 584 | features |= NF_CT_F_HELP; |
584 | read_unlock_bh(&nf_conntrack_lock); | 585 | read_unlock_bh(&nf_conntrack_lock); |
585 | 586 | ||
@@ -850,6 +851,26 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, | |||
850 | orig->dst.protonum)); | 851 | orig->dst.protonum)); |
851 | } | 852 | } |
852 | 853 | ||
854 | /* Alter reply tuple (maybe alter helper). This is for NAT, and is | ||
855 | implicitly racy: see __nf_conntrack_confirm */ | ||
856 | void nf_conntrack_alter_reply(struct nf_conn *ct, | ||
857 | const struct nf_conntrack_tuple *newreply) | ||
858 | { | ||
859 | struct nf_conn_help *help = nfct_help(ct); | ||
860 | |||
861 | write_lock_bh(&nf_conntrack_lock); | ||
862 | /* Should be unconfirmed, so not in hash table yet */ | ||
863 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); | ||
864 | |||
865 | DEBUGP("Altering reply tuple of %p to ", ct); | ||
866 | NF_CT_DUMP_TUPLE(newreply); | ||
867 | |||
868 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; | ||
869 | if (!ct->master && help && help->expecting == 0) | ||
870 | help->helper = __nf_ct_helper_find(newreply); | ||
871 | write_unlock_bh(&nf_conntrack_lock); | ||
872 | } | ||
873 | |||
853 | /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */ | 874 | /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */ |
854 | void __nf_ct_refresh_acct(struct nf_conn *ct, | 875 | void __nf_ct_refresh_acct(struct nf_conn *ct, |
855 | enum ip_conntrack_info ctinfo, | 876 | enum ip_conntrack_info ctinfo, |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index f9c8ddd5973c..bd1d2de75e45 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -39,7 +39,11 @@ | |||
39 | #include <net/netfilter/nf_conntrack_helper.h> | 39 | #include <net/netfilter/nf_conntrack_helper.h> |
40 | #include <net/netfilter/nf_conntrack_l3proto.h> | 40 | #include <net/netfilter/nf_conntrack_l3proto.h> |
41 | #include <net/netfilter/nf_conntrack_l4proto.h> | 41 | #include <net/netfilter/nf_conntrack_l4proto.h> |
42 | #include <linux/netfilter_ipv4/ip_nat_protocol.h> | 42 | #include <net/netfilter/nf_conntrack_tuple.h> |
43 | #ifdef CONFIG_NF_NAT_NEEDED | ||
44 | #include <net/netfilter/nf_nat_core.h> | ||
45 | #include <net/netfilter/nf_nat_protocol.h> | ||
46 | #endif | ||
43 | 47 | ||
44 | #include <linux/netfilter/nfnetlink.h> | 48 | #include <linux/netfilter/nfnetlink.h> |
45 | #include <linux/netfilter/nfnetlink_conntrack.h> | 49 | #include <linux/netfilter/nfnetlink_conntrack.h> |
@@ -430,7 +434,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
430 | restart: | 434 | restart: |
431 | list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { | 435 | list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { |
432 | h = (struct nf_conntrack_tuple_hash *) i; | 436 | h = (struct nf_conntrack_tuple_hash *) i; |
433 | if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) | 437 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) |
434 | continue; | 438 | continue; |
435 | ct = nf_ct_tuplehash_to_ctrack(h); | 439 | ct = nf_ct_tuplehash_to_ctrack(h); |
436 | /* Dump entries of a given L3 protocol number. | 440 | /* Dump entries of a given L3 protocol number. |
@@ -556,28 +560,28 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple, | |||
556 | return 0; | 560 | return 0; |
557 | } | 561 | } |
558 | 562 | ||
559 | #ifdef CONFIG_IP_NF_NAT_NEEDED | 563 | #ifdef CONFIG_NF_NAT_NEEDED |
560 | static const size_t cta_min_protonat[CTA_PROTONAT_MAX] = { | 564 | static const size_t cta_min_protonat[CTA_PROTONAT_MAX] = { |
561 | [CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t), | 565 | [CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t), |
562 | [CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t), | 566 | [CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t), |
563 | }; | 567 | }; |
564 | 568 | ||
565 | static int ctnetlink_parse_nat_proto(struct nfattr *attr, | 569 | static int nfnetlink_parse_nat_proto(struct nfattr *attr, |
566 | const struct nf_conn *ct, | 570 | const struct nf_conn *ct, |
567 | struct ip_nat_range *range) | 571 | struct nf_nat_range *range) |
568 | { | 572 | { |
569 | struct nfattr *tb[CTA_PROTONAT_MAX]; | 573 | struct nfattr *tb[CTA_PROTONAT_MAX]; |
570 | struct ip_nat_protocol *npt; | 574 | struct nf_nat_protocol *npt; |
571 | 575 | ||
572 | nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); | 576 | nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); |
573 | 577 | ||
574 | if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) | 578 | if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) |
575 | return -EINVAL; | 579 | return -EINVAL; |
576 | 580 | ||
577 | npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); | 581 | npt = nf_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); |
578 | 582 | ||
579 | if (!npt->nfattr_to_range) { | 583 | if (!npt->nfattr_to_range) { |
580 | ip_nat_proto_put(npt); | 584 | nf_nat_proto_put(npt); |
581 | return 0; | 585 | return 0; |
582 | } | 586 | } |
583 | 587 | ||
@@ -585,7 +589,7 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, | |||
585 | if (npt->nfattr_to_range(tb, range) > 0) | 589 | if (npt->nfattr_to_range(tb, range) > 0) |
586 | range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; | 590 | range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; |
587 | 591 | ||
588 | ip_nat_proto_put(npt); | 592 | nf_nat_proto_put(npt); |
589 | 593 | ||
590 | return 0; | 594 | return 0; |
591 | } | 595 | } |
@@ -596,8 +600,8 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = { | |||
596 | }; | 600 | }; |
597 | 601 | ||
598 | static inline int | 602 | static inline int |
599 | ctnetlink_parse_nat(struct nfattr *nat, | 603 | nfnetlink_parse_nat(struct nfattr *nat, |
600 | const struct nf_conn *ct, struct ip_nat_range *range) | 604 | const struct nf_conn *ct, struct nf_nat_range *range) |
601 | { | 605 | { |
602 | struct nfattr *tb[CTA_NAT_MAX]; | 606 | struct nfattr *tb[CTA_NAT_MAX]; |
603 | int err; | 607 | int err; |
@@ -623,7 +627,7 @@ ctnetlink_parse_nat(struct nfattr *nat, | |||
623 | if (!tb[CTA_NAT_PROTO-1]) | 627 | if (!tb[CTA_NAT_PROTO-1]) |
624 | return 0; | 628 | return 0; |
625 | 629 | ||
626 | err = ctnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range); | 630 | err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range); |
627 | if (err < 0) | 631 | if (err < 0) |
628 | return err; | 632 | return err; |
629 | 633 | ||
@@ -798,35 +802,35 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[]) | |||
798 | return -EINVAL; | 802 | return -EINVAL; |
799 | 803 | ||
800 | if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) { | 804 | if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) { |
801 | #ifndef CONFIG_IP_NF_NAT_NEEDED | 805 | #ifndef CONFIG_NF_NAT_NEEDED |
802 | return -EINVAL; | 806 | return -EINVAL; |
803 | #else | 807 | #else |
804 | struct ip_nat_range range; | 808 | struct nf_nat_range range; |
805 | 809 | ||
806 | if (cda[CTA_NAT_DST-1]) { | 810 | if (cda[CTA_NAT_DST-1]) { |
807 | if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct, | 811 | if (nfnetlink_parse_nat(cda[CTA_NAT_DST-1], ct, |
808 | &range) < 0) | 812 | &range) < 0) |
809 | return -EINVAL; | 813 | return -EINVAL; |
810 | if (ip_nat_initialized(ct, | 814 | if (nf_nat_initialized(ct, |
811 | HOOK2MANIP(NF_IP_PRE_ROUTING))) | 815 | HOOK2MANIP(NF_IP_PRE_ROUTING))) |
812 | return -EEXIST; | 816 | return -EEXIST; |
813 | ip_nat_setup_info(ct, &range, hooknum); | 817 | nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); |
814 | } | 818 | } |
815 | if (cda[CTA_NAT_SRC-1]) { | 819 | if (cda[CTA_NAT_SRC-1]) { |
816 | if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct, | 820 | if (nfnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct, |
817 | &range) < 0) | 821 | &range) < 0) |
818 | return -EINVAL; | 822 | return -EINVAL; |
819 | if (ip_nat_initialized(ct, | 823 | if (nf_nat_initialized(ct, |
820 | HOOK2MANIP(NF_IP_POST_ROUTING))) | 824 | HOOK2MANIP(NF_IP_POST_ROUTING))) |
821 | return -EEXIST; | 825 | return -EEXIST; |
822 | ip_nat_setup_info(ct, &range, hooknum); | 826 | nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); |
823 | } | 827 | } |
824 | #endif | 828 | #endif |
825 | } | 829 | } |
826 | 830 | ||
827 | /* Be careful here, modifying NAT bits can screw up things, | 831 | /* Be careful here, modifying NAT bits can screw up things, |
828 | * so don't let users modify them directly if they don't pass | 832 | * so don't let users modify them directly if they don't pass |
829 | * ip_nat_range. */ | 833 | * nf_nat_range. */ |
830 | ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK); | 834 | ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK); |
831 | return 0; | 835 | return 0; |
832 | } | 836 | } |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 71f492fc6413..8156e429b885 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -730,7 +730,7 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
730 | return res; | 730 | return res; |
731 | } | 731 | } |
732 | 732 | ||
733 | #ifdef CONFIG_IP_NF_NAT_NEEDED | 733 | #ifdef CONFIG_NF_NAT_NEEDED |
734 | /* Update sender->td_end after NAT successfully mangled the packet */ | 734 | /* Update sender->td_end after NAT successfully mangled the packet */ |
735 | /* Caller must linearize skb at tcp header. */ | 735 | /* Caller must linearize skb at tcp header. */ |
736 | void nf_conntrack_tcp_update(struct sk_buff *skb, | 736 | void nf_conntrack_tcp_update(struct sk_buff *skb, |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index be94b6359725..3f56a3a6c399 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -530,8 +530,11 @@ EXPORT_SYMBOL(nf_conntrack_lock); | |||
530 | EXPORT_SYMBOL(nf_conntrack_hash); | 530 | EXPORT_SYMBOL(nf_conntrack_hash); |
531 | EXPORT_SYMBOL(nf_conntrack_untracked); | 531 | EXPORT_SYMBOL(nf_conntrack_untracked); |
532 | EXPORT_SYMBOL_GPL(nf_conntrack_find_get); | 532 | EXPORT_SYMBOL_GPL(nf_conntrack_find_get); |
533 | #ifdef CONFIG_IP_NF_NAT_NEEDED | 533 | #ifdef CONFIG_NF_NAT_NEEDED |
534 | EXPORT_SYMBOL(nf_conntrack_tcp_update); | 534 | EXPORT_SYMBOL(nf_conntrack_tcp_update); |
535 | EXPORT_SYMBOL(nf_conntrack_register_cache); | ||
536 | EXPORT_SYMBOL(nf_conntrack_unregister_cache); | ||
537 | EXPORT_SYMBOL(nf_conntrack_alter_reply); | ||
535 | #endif | 538 | #endif |
536 | EXPORT_SYMBOL(__nf_conntrack_confirm); | 539 | EXPORT_SYMBOL(__nf_conntrack_confirm); |
537 | EXPORT_SYMBOL(nf_ct_get_tuple); | 540 | EXPORT_SYMBOL(nf_ct_get_tuple); |