aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2014-11-14 07:21:48 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2014-11-17 06:44:20 -0500
commite59ea3df3fc290b91c52a250c19091c18b4e6d7e (patch)
tree20e3e6a02a4168c7af67285c96b369bdf31d1722 /net/netfilter
parent8225161545a67bdb68cf86beafcdce1604720605 (diff)
netfilter: xt_connlimit: honor conntrack zone if available
Currently all the conntrack lookups are done using default zone. In case the skb has a ct attached (e.g. template) we should use this zone for lookups instead. This makes connlimit work with connections assigned to other zones. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/xt_connlimit.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index fbc66bb250d5..29ba6218a820 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -134,6 +134,7 @@ static bool add_hlist(struct hlist_head *head,
134static unsigned int check_hlist(struct net *net, 134static unsigned int check_hlist(struct net *net,
135 struct hlist_head *head, 135 struct hlist_head *head,
136 const struct nf_conntrack_tuple *tuple, 136 const struct nf_conntrack_tuple *tuple,
137 u16 zone,
137 bool *addit) 138 bool *addit)
138{ 139{
139 const struct nf_conntrack_tuple_hash *found; 140 const struct nf_conntrack_tuple_hash *found;
@@ -147,8 +148,7 @@ static unsigned int check_hlist(struct net *net,
147 148
148 /* check the saved connections */ 149 /* check the saved connections */
149 hlist_for_each_entry_safe(conn, n, head, node) { 150 hlist_for_each_entry_safe(conn, n, head, node) {
150 found = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE, 151 found = nf_conntrack_find_get(net, zone, &conn->tuple);
151 &conn->tuple);
152 if (found == NULL) { 152 if (found == NULL) {
153 hlist_del(&conn->node); 153 hlist_del(&conn->node);
154 kmem_cache_free(connlimit_conn_cachep, conn); 154 kmem_cache_free(connlimit_conn_cachep, conn);
@@ -201,7 +201,7 @@ static unsigned int
201count_tree(struct net *net, struct rb_root *root, 201count_tree(struct net *net, struct rb_root *root,
202 const struct nf_conntrack_tuple *tuple, 202 const struct nf_conntrack_tuple *tuple,
203 const union nf_inet_addr *addr, const union nf_inet_addr *mask, 203 const union nf_inet_addr *addr, const union nf_inet_addr *mask,
204 u8 family) 204 u8 family, u16 zone)
205{ 205{
206 struct xt_connlimit_rb *gc_nodes[CONNLIMIT_GC_MAX_NODES]; 206 struct xt_connlimit_rb *gc_nodes[CONNLIMIT_GC_MAX_NODES];
207 struct rb_node **rbnode, *parent; 207 struct rb_node **rbnode, *parent;
@@ -229,7 +229,7 @@ count_tree(struct net *net, struct rb_root *root,
229 } else { 229 } else {
230 /* same source network -> be counted! */ 230 /* same source network -> be counted! */
231 unsigned int count; 231 unsigned int count;
232 count = check_hlist(net, &rbconn->hhead, tuple, &addit); 232 count = check_hlist(net, &rbconn->hhead, tuple, zone, &addit);
233 233
234 tree_nodes_free(root, gc_nodes, gc_count); 234 tree_nodes_free(root, gc_nodes, gc_count);
235 if (!addit) 235 if (!addit)
@@ -245,7 +245,7 @@ count_tree(struct net *net, struct rb_root *root,
245 continue; 245 continue;
246 246
247 /* only used for GC on hhead, retval and 'addit' ignored */ 247 /* only used for GC on hhead, retval and 'addit' ignored */
248 check_hlist(net, &rbconn->hhead, tuple, &addit); 248 check_hlist(net, &rbconn->hhead, tuple, zone, &addit);
249 if (hlist_empty(&rbconn->hhead)) 249 if (hlist_empty(&rbconn->hhead))
250 gc_nodes[gc_count++] = rbconn; 250 gc_nodes[gc_count++] = rbconn;
251 } 251 }
@@ -290,7 +290,7 @@ static int count_them(struct net *net,
290 const struct nf_conntrack_tuple *tuple, 290 const struct nf_conntrack_tuple *tuple,
291 const union nf_inet_addr *addr, 291 const union nf_inet_addr *addr,
292 const union nf_inet_addr *mask, 292 const union nf_inet_addr *mask,
293 u_int8_t family) 293 u_int8_t family, u16 zone)
294{ 294{
295 struct rb_root *root; 295 struct rb_root *root;
296 int count; 296 int count;
@@ -306,7 +306,7 @@ static int count_them(struct net *net,
306 306
307 spin_lock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]); 307 spin_lock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
308 308
309 count = count_tree(net, root, tuple, addr, mask, family); 309 count = count_tree(net, root, tuple, addr, mask, family, zone);
310 310
311 spin_unlock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]); 311 spin_unlock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
312 312
@@ -324,13 +324,16 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
324 enum ip_conntrack_info ctinfo; 324 enum ip_conntrack_info ctinfo;
325 const struct nf_conn *ct; 325 const struct nf_conn *ct;
326 unsigned int connections; 326 unsigned int connections;
327 u16 zone = NF_CT_DEFAULT_ZONE;
327 328
328 ct = nf_ct_get(skb, &ctinfo); 329 ct = nf_ct_get(skb, &ctinfo);
329 if (ct != NULL) 330 if (ct != NULL) {
330 tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; 331 tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
331 else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), 332 zone = nf_ct_zone(ct);
332 par->family, &tuple)) 333 } else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
334 par->family, &tuple)) {
333 goto hotdrop; 335 goto hotdrop;
336 }
334 337
335 if (par->family == NFPROTO_IPV6) { 338 if (par->family == NFPROTO_IPV6) {
336 const struct ipv6hdr *iph = ipv6_hdr(skb); 339 const struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -343,7 +346,7 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
343 } 346 }
344 347
345 connections = count_them(net, info->data, tuple_ptr, &addr, 348 connections = count_them(net, info->data, tuple_ptr, &addr,
346 &info->mask, par->family); 349 &info->mask, par->family, zone);
347 if (connections == 0) 350 if (connections == 0)
348 /* kmalloc failed, drop it entirely */ 351 /* kmalloc failed, drop it entirely */
349 goto hotdrop; 352 goto hotdrop;