aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChangli Gao <xiaosuo@gmail.com>2011-03-15 08:23:28 -0400
committerPatrick McHardy <kaber@trash.net>2011-03-15 08:23:28 -0400
commit8183e3a88aced228ab9770762692be6cc3786e80 (patch)
tree091cf02201486f436cbc0596aadf51dafbc3784a /net
parentf2247fbdc41372d64c89505280419ceb45d80a31 (diff)
netfilter: xt_connlimit: fix daddr connlimit in SNAT scenario
We use the reply tuples when limiting the connections by the destination addresses, however, in SNAT scenario, the final reply tuples won't be ready until SNAT is done in POSTROUING or INPUT chain, and the following nf_conntrack_find_get() in count_tem() will get nothing, so connlimit can't work as expected. In this patch, the original tuples are always used, and an additional member addr is appended to save the address in either end. Signed-off-by: Changli Gao <xiaosuo@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/xt_connlimit.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index e029c4807404..1f4b9f9da496 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -33,8 +33,9 @@
33 33
34/* we will save the tuples of all connections we care about */ 34/* we will save the tuples of all connections we care about */
35struct xt_connlimit_conn { 35struct xt_connlimit_conn {
36 struct list_head list; 36 struct list_head list;
37 struct nf_conntrack_tuple tuple; 37 struct nf_conntrack_tuple tuple;
38 union nf_inet_addr addr;
38}; 39};
39 40
40struct xt_connlimit_data { 41struct xt_connlimit_data {
@@ -151,7 +152,7 @@ static int count_them(struct net *net,
151 continue; 152 continue;
152 } 153 }
153 154
154 if (same_source_net(addr, mask, &conn->tuple.src.u3, family)) 155 if (same_source_net(addr, mask, &conn->addr, family))
155 /* same source network -> be counted! */ 156 /* same source network -> be counted! */
156 ++matches; 157 ++matches;
157 nf_ct_put(found_ct); 158 nf_ct_put(found_ct);
@@ -165,6 +166,7 @@ static int count_them(struct net *net,
165 if (conn == NULL) 166 if (conn == NULL)
166 return -ENOMEM; 167 return -ENOMEM;
167 conn->tuple = *tuple; 168 conn->tuple = *tuple;
169 conn->addr = *addr;
168 list_add(&conn->list, hash); 170 list_add(&conn->list, hash);
169 ++matches; 171 ++matches;
170 } 172 }
@@ -185,15 +187,11 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
185 int connections; 187 int connections;
186 188
187 ct = nf_ct_get(skb, &ctinfo); 189 ct = nf_ct_get(skb, &ctinfo);
188 if (ct != NULL) { 190 if (ct != NULL)
189 if (info->flags & XT_CONNLIMIT_DADDR) 191 tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
190 tuple_ptr = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; 192 else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
191 else 193 par->family, &tuple))
192 tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
193 } else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
194 par->family, &tuple)) {
195 goto hotdrop; 194 goto hotdrop;
196 }
197 195
198 if (par->family == NFPROTO_IPV6) { 196 if (par->family == NFPROTO_IPV6) {
199 const struct ipv6hdr *iph = ipv6_hdr(skb); 197 const struct ipv6hdr *iph = ipv6_hdr(skb);