diff options
author | Patrick McHardy <kaber@trash.net> | 2006-05-29 21:24:39 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-18 00:29:01 -0400 |
commit | 3726add76643c715d437aceda320d319153b6113 (patch) | |
tree | 70b343ab57ae6575ebc2828cc1e8bab24c4df120 | |
parent | 997ae831ade74bdaed4172b1c02060b9efd6e206 (diff) |
[NETFILTER]: ctnetlink: fix NAT configuration
The current configuration only allows to configure one manip and overloads
conntrack status flags with netlink semantic.
Signed-off-by: Patrick Mchardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netfilter/nfnetlink_conntrack.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_netlink.c | 53 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 53 |
3 files changed, 47 insertions, 63 deletions
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index 668ec946c8e2..b5883ccee295 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h | |||
@@ -27,13 +27,15 @@ enum ctattr_type { | |||
27 | CTA_STATUS, | 27 | CTA_STATUS, |
28 | CTA_PROTOINFO, | 28 | CTA_PROTOINFO, |
29 | CTA_HELP, | 29 | CTA_HELP, |
30 | CTA_NAT, | 30 | CTA_NAT_SRC, |
31 | #define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ | ||
31 | CTA_TIMEOUT, | 32 | CTA_TIMEOUT, |
32 | CTA_MARK, | 33 | CTA_MARK, |
33 | CTA_COUNTERS_ORIG, | 34 | CTA_COUNTERS_ORIG, |
34 | CTA_COUNTERS_REPLY, | 35 | CTA_COUNTERS_REPLY, |
35 | CTA_USE, | 36 | CTA_USE, |
36 | CTA_ID, | 37 | CTA_ID, |
38 | CTA_NAT_DST, | ||
37 | __CTA_MAX | 39 | __CTA_MAX |
38 | }; | 40 | }; |
39 | #define CTA_MAX (__CTA_MAX - 1) | 41 | #define CTA_MAX (__CTA_MAX - 1) |
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 01bd7cab9367..af152e3623dc 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c | |||
@@ -629,7 +629,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = { | |||
629 | }; | 629 | }; |
630 | 630 | ||
631 | static inline int | 631 | static inline int |
632 | ctnetlink_parse_nat(struct nfattr *cda[], | 632 | ctnetlink_parse_nat(struct nfattr *nat, |
633 | const struct ip_conntrack *ct, struct ip_nat_range *range) | 633 | const struct ip_conntrack *ct, struct ip_nat_range *range) |
634 | { | 634 | { |
635 | struct nfattr *tb[CTA_NAT_MAX]; | 635 | struct nfattr *tb[CTA_NAT_MAX]; |
@@ -639,7 +639,7 @@ ctnetlink_parse_nat(struct nfattr *cda[], | |||
639 | 639 | ||
640 | memset(range, 0, sizeof(*range)); | 640 | memset(range, 0, sizeof(*range)); |
641 | 641 | ||
642 | nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); | 642 | nfattr_parse_nested(tb, CTA_NAT_MAX, nat); |
643 | 643 | ||
644 | if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat)) | 644 | if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat)) |
645 | return -EINVAL; | 645 | return -EINVAL; |
@@ -854,39 +854,30 @@ ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[]) | |||
854 | /* ASSURED bit can only be set */ | 854 | /* ASSURED bit can only be set */ |
855 | return -EINVAL; | 855 | return -EINVAL; |
856 | 856 | ||
857 | if (cda[CTA_NAT-1]) { | 857 | if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) { |
858 | #ifndef CONFIG_IP_NF_NAT_NEEDED | 858 | #ifndef CONFIG_IP_NF_NAT_NEEDED |
859 | return -EINVAL; | 859 | return -EINVAL; |
860 | #else | 860 | #else |
861 | unsigned int hooknum; | ||
862 | struct ip_nat_range range; | 861 | struct ip_nat_range range; |
863 | 862 | ||
864 | if (ctnetlink_parse_nat(cda, ct, &range) < 0) | 863 | if (cda[CTA_NAT_DST-1]) { |
865 | return -EINVAL; | 864 | if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct, |
866 | 865 | &range) < 0) | |
867 | DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n", | 866 | return -EINVAL; |
868 | NIPQUAD(range.min_ip), NIPQUAD(range.max_ip), | 867 | if (ip_nat_initialized(ct, |
869 | htons(range.min.all), htons(range.max.all)); | 868 | HOOK2MANIP(NF_IP_PRE_ROUTING))) |
870 | 869 | return -EEXIST; | |
871 | /* This is tricky but it works. ip_nat_setup_info needs the | 870 | ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); |
872 | * hook number as parameter, so let's do the correct | 871 | } |
873 | * conversion and run away */ | 872 | if (cda[CTA_NAT_SRC-1]) { |
874 | if (status & IPS_SRC_NAT_DONE) | 873 | if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct, |
875 | hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */ | 874 | &range) < 0) |
876 | else if (status & IPS_DST_NAT_DONE) | 875 | return -EINVAL; |
877 | hooknum = NF_IP_PRE_ROUTING; /* IP_NAT_MANIP_DST */ | 876 | if (ip_nat_initialized(ct, |
878 | else | 877 | HOOK2MANIP(NF_IP_POST_ROUTING))) |
879 | return -EINVAL; /* Missing NAT flags */ | 878 | return -EEXIST; |
880 | 879 | ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); | |
881 | DEBUGP("NAT status: %lu\n", | 880 | } |
882 | status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK)); | ||
883 | |||
884 | if (ip_nat_initialized(ct, HOOK2MANIP(hooknum))) | ||
885 | return -EEXIST; | ||
886 | ip_nat_setup_info(ct, &range, hooknum); | ||
887 | |||
888 | DEBUGP("NAT status after setup_info: %lu\n", | ||
889 | ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK)); | ||
890 | #endif | 881 | #endif |
891 | } | 882 | } |
892 | 883 | ||
@@ -1106,7 +1097,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1106 | /* implicit 'else' */ | 1097 | /* implicit 'else' */ |
1107 | 1098 | ||
1108 | /* we only allow nat config for new conntracks */ | 1099 | /* we only allow nat config for new conntracks */ |
1109 | if (cda[CTA_NAT-1]) { | 1100 | if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) { |
1110 | err = -EINVAL; | 1101 | err = -EINVAL; |
1111 | goto out_unlock; | 1102 | goto out_unlock; |
1112 | } | 1103 | } |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index bd10eb944b65..8f27fe9446f2 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -641,7 +641,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = { | |||
641 | }; | 641 | }; |
642 | 642 | ||
643 | static inline int | 643 | static inline int |
644 | ctnetlink_parse_nat(struct nfattr *cda[], | 644 | ctnetlink_parse_nat(struct nfattr *nat, |
645 | const struct nf_conn *ct, struct ip_nat_range *range) | 645 | const struct nf_conn *ct, struct ip_nat_range *range) |
646 | { | 646 | { |
647 | struct nfattr *tb[CTA_NAT_MAX]; | 647 | struct nfattr *tb[CTA_NAT_MAX]; |
@@ -651,7 +651,7 @@ ctnetlink_parse_nat(struct nfattr *cda[], | |||
651 | 651 | ||
652 | memset(range, 0, sizeof(*range)); | 652 | memset(range, 0, sizeof(*range)); |
653 | 653 | ||
654 | nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); | 654 | nfattr_parse_nested(tb, CTA_NAT_MAX, nat); |
655 | 655 | ||
656 | if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat)) | 656 | if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat)) |
657 | return -EINVAL; | 657 | return -EINVAL; |
@@ -866,39 +866,30 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[]) | |||
866 | /* ASSURED bit can only be set */ | 866 | /* ASSURED bit can only be set */ |
867 | return -EINVAL; | 867 | return -EINVAL; |
868 | 868 | ||
869 | if (cda[CTA_NAT-1]) { | 869 | if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) { |
870 | #ifndef CONFIG_IP_NF_NAT_NEEDED | 870 | #ifndef CONFIG_IP_NF_NAT_NEEDED |
871 | return -EINVAL; | 871 | return -EINVAL; |
872 | #else | 872 | #else |
873 | unsigned int hooknum; | ||
874 | struct ip_nat_range range; | 873 | struct ip_nat_range range; |
875 | 874 | ||
876 | if (ctnetlink_parse_nat(cda, ct, &range) < 0) | 875 | if (cda[CTA_NAT_DST-1]) { |
877 | return -EINVAL; | 876 | if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct, |
878 | 877 | &range) < 0) | |
879 | DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n", | 878 | return -EINVAL; |
880 | NIPQUAD(range.min_ip), NIPQUAD(range.max_ip), | 879 | if (ip_nat_initialized(ct, |
881 | htons(range.min.all), htons(range.max.all)); | 880 | HOOK2MANIP(NF_IP_PRE_ROUTING))) |
882 | 881 | return -EEXIST; | |
883 | /* This is tricky but it works. ip_nat_setup_info needs the | 882 | ip_nat_setup_info(ct, &range, hooknum); |
884 | * hook number as parameter, so let's do the correct | 883 | } |
885 | * conversion and run away */ | 884 | if (cda[CTA_NAT_SRC-1]) { |
886 | if (status & IPS_SRC_NAT_DONE) | 885 | if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct, |
887 | hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */ | 886 | &range) < 0) |
888 | else if (status & IPS_DST_NAT_DONE) | 887 | return -EINVAL; |
889 | hooknum = NF_IP_PRE_ROUTING; /* IP_NAT_MANIP_DST */ | 888 | if (ip_nat_initialized(ct, |
890 | else | 889 | HOOK2MANIP(NF_IP_POST_ROUTING))) |
891 | return -EINVAL; /* Missing NAT flags */ | 890 | return -EEXIST; |
892 | 891 | ip_nat_setup_info(ct, &range, hooknum); | |
893 | DEBUGP("NAT status: %lu\n", | 892 | } |
894 | status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK)); | ||
895 | |||
896 | if (ip_nat_initialized(ct, HOOK2MANIP(hooknum))) | ||
897 | return -EEXIST; | ||
898 | ip_nat_setup_info(ct, &range, hooknum); | ||
899 | |||
900 | DEBUGP("NAT status after setup_info: %lu\n", | ||
901 | ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK)); | ||
902 | #endif | 893 | #endif |
903 | } | 894 | } |
904 | 895 | ||
@@ -1122,7 +1113,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1122 | /* implicit 'else' */ | 1113 | /* implicit 'else' */ |
1123 | 1114 | ||
1124 | /* we only allow nat config for new conntracks */ | 1115 | /* we only allow nat config for new conntracks */ |
1125 | if (cda[CTA_NAT-1]) { | 1116 | if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) { |
1126 | err = -EINVAL; | 1117 | err = -EINVAL; |
1127 | goto out_unlock; | 1118 | goto out_unlock; |
1128 | } | 1119 | } |