diff options
25 files changed, 236 insertions, 85 deletions
diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h index 7fd0effe1316..1b564106891d 100644 --- a/include/linux/netfilter/xt_CT.h +++ b/include/linux/netfilter/xt_CT.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | struct xt_ct_target_info { | 6 | struct xt_ct_target_info { |
| 7 | u_int16_t flags; | 7 | u_int16_t flags; |
| 8 | u_int16_t __unused; | 8 | u_int16_t zone; |
| 9 | u_int32_t ct_events; | 9 | u_int32_t ct_events; |
| 10 | u_int32_t exp_events; | 10 | u_int32_t exp_events; |
| 11 | char helper[16]; | 11 | char helper[16]; |
diff --git a/include/net/ip.h b/include/net/ip.h index fb63371c07a8..7bc47873e3fc 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
| @@ -352,8 +352,11 @@ enum ip_defrag_users { | |||
| 352 | IP_DEFRAG_LOCAL_DELIVER, | 352 | IP_DEFRAG_LOCAL_DELIVER, |
| 353 | IP_DEFRAG_CALL_RA_CHAIN, | 353 | IP_DEFRAG_CALL_RA_CHAIN, |
| 354 | IP_DEFRAG_CONNTRACK_IN, | 354 | IP_DEFRAG_CONNTRACK_IN, |
| 355 | __IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHORT_MAX, | ||
| 355 | IP_DEFRAG_CONNTRACK_OUT, | 356 | IP_DEFRAG_CONNTRACK_OUT, |
| 357 | __IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHORT_MAX, | ||
| 356 | IP_DEFRAG_CONNTRACK_BRIDGE_IN, | 358 | IP_DEFRAG_CONNTRACK_BRIDGE_IN, |
| 359 | __IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHORT_MAX, | ||
| 357 | IP_DEFRAG_VS_IN, | 360 | IP_DEFRAG_VS_IN, |
| 358 | IP_DEFRAG_VS_OUT, | 361 | IP_DEFRAG_VS_OUT, |
| 359 | IP_DEFRAG_VS_FWD | 362 | IP_DEFRAG_VS_FWD |
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 299bbf5adfb6..639ec53ea081 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
| @@ -355,8 +355,11 @@ struct inet_frag_queue; | |||
| 355 | enum ip6_defrag_users { | 355 | enum ip6_defrag_users { |
| 356 | IP6_DEFRAG_LOCAL_DELIVER, | 356 | IP6_DEFRAG_LOCAL_DELIVER, |
| 357 | IP6_DEFRAG_CONNTRACK_IN, | 357 | IP6_DEFRAG_CONNTRACK_IN, |
| 358 | __IP6_DEFRAG_CONNTRACK_IN = IP6_DEFRAG_CONNTRACK_IN + USHORT_MAX, | ||
| 358 | IP6_DEFRAG_CONNTRACK_OUT, | 359 | IP6_DEFRAG_CONNTRACK_OUT, |
| 360 | __IP6_DEFRAG_CONNTRACK_OUT = IP6_DEFRAG_CONNTRACK_OUT + USHORT_MAX, | ||
| 359 | IP6_DEFRAG_CONNTRACK_BRIDGE_IN, | 361 | IP6_DEFRAG_CONNTRACK_BRIDGE_IN, |
| 362 | __IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHORT_MAX, | ||
| 360 | }; | 363 | }; |
| 361 | 364 | ||
| 362 | struct ip6_create_arg { | 365 | struct ip6_create_arg { |
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 5b7d8835523f..bde095f7e845 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
| @@ -198,7 +198,8 @@ extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int null | |||
| 198 | extern void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size); | 198 | extern void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size); |
| 199 | 199 | ||
| 200 | extern struct nf_conntrack_tuple_hash * | 200 | extern struct nf_conntrack_tuple_hash * |
| 201 | __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple); | 201 | __nf_conntrack_find(struct net *net, u16 zone, |
| 202 | const struct nf_conntrack_tuple *tuple); | ||
| 202 | 203 | ||
| 203 | extern void nf_conntrack_hash_insert(struct nf_conn *ct); | 204 | extern void nf_conntrack_hash_insert(struct nf_conn *ct); |
| 204 | extern void nf_ct_delete_from_lists(struct nf_conn *ct); | 205 | extern void nf_ct_delete_from_lists(struct nf_conn *ct); |
| @@ -267,7 +268,7 @@ extern void | |||
| 267 | nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data); | 268 | nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data); |
| 268 | extern void nf_conntrack_free(struct nf_conn *ct); | 269 | extern void nf_conntrack_free(struct nf_conn *ct); |
| 269 | extern struct nf_conn * | 270 | extern struct nf_conn * |
| 270 | nf_conntrack_alloc(struct net *net, | 271 | nf_conntrack_alloc(struct net *net, u16 zone, |
| 271 | const struct nf_conntrack_tuple *orig, | 272 | const struct nf_conntrack_tuple *orig, |
| 272 | const struct nf_conntrack_tuple *repl, | 273 | const struct nf_conntrack_tuple *repl, |
| 273 | gfp_t gfp); | 274 | gfp_t gfp); |
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 5a449b44ba33..dffde8e6920e 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h | |||
| @@ -49,7 +49,8 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, | |||
| 49 | 49 | ||
| 50 | /* Find a connection corresponding to a tuple. */ | 50 | /* Find a connection corresponding to a tuple. */ |
| 51 | extern struct nf_conntrack_tuple_hash * | 51 | extern struct nf_conntrack_tuple_hash * |
| 52 | nf_conntrack_find_get(struct net *net, const struct nf_conntrack_tuple *tuple); | 52 | nf_conntrack_find_get(struct net *net, u16 zone, |
| 53 | const struct nf_conntrack_tuple *tuple); | ||
| 53 | 54 | ||
| 54 | extern int __nf_conntrack_confirm(struct sk_buff *skb); | 55 | extern int __nf_conntrack_confirm(struct sk_buff *skb); |
| 55 | 56 | ||
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 4b47ec19ef39..11e815084fcf 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h | |||
| @@ -74,13 +74,16 @@ int nf_conntrack_expect_init(struct net *net); | |||
| 74 | void nf_conntrack_expect_fini(struct net *net); | 74 | void nf_conntrack_expect_fini(struct net *net); |
| 75 | 75 | ||
| 76 | struct nf_conntrack_expect * | 76 | struct nf_conntrack_expect * |
| 77 | __nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple); | 77 | __nf_ct_expect_find(struct net *net, u16 zone, |
| 78 | const struct nf_conntrack_tuple *tuple); | ||
| 78 | 79 | ||
| 79 | struct nf_conntrack_expect * | 80 | struct nf_conntrack_expect * |
| 80 | nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple); | 81 | nf_ct_expect_find_get(struct net *net, u16 zone, |
| 82 | const struct nf_conntrack_tuple *tuple); | ||
| 81 | 83 | ||
| 82 | struct nf_conntrack_expect * | 84 | struct nf_conntrack_expect * |
| 83 | nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple); | 85 | nf_ct_find_expectation(struct net *net, u16 zone, |
| 86 | const struct nf_conntrack_tuple *tuple); | ||
| 84 | 87 | ||
| 85 | void nf_ct_unlink_expect(struct nf_conntrack_expect *exp); | 88 | void nf_ct_unlink_expect(struct nf_conntrack_expect *exp); |
| 86 | void nf_ct_remove_expectations(struct nf_conn *ct); | 89 | void nf_ct_remove_expectations(struct nf_conn *ct); |
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index e192dc17c583..2d2a1f9a61d8 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h | |||
| @@ -8,6 +8,7 @@ enum nf_ct_ext_id { | |||
| 8 | NF_CT_EXT_NAT, | 8 | NF_CT_EXT_NAT, |
| 9 | NF_CT_EXT_ACCT, | 9 | NF_CT_EXT_ACCT, |
| 10 | NF_CT_EXT_ECACHE, | 10 | NF_CT_EXT_ECACHE, |
| 11 | NF_CT_EXT_ZONE, | ||
| 11 | NF_CT_EXT_NUM, | 12 | NF_CT_EXT_NUM, |
| 12 | }; | 13 | }; |
| 13 | 14 | ||
| @@ -15,6 +16,7 @@ enum nf_ct_ext_id { | |||
| 15 | #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat | 16 | #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat |
| 16 | #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter | 17 | #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter |
| 17 | #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache | 18 | #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache |
| 19 | #define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone | ||
| 18 | 20 | ||
| 19 | /* Extensions: optional stuff which isn't permanently in struct. */ | 21 | /* Extensions: optional stuff which isn't permanently in struct. */ |
| 20 | struct nf_ct_ext { | 22 | struct nf_ct_ext { |
diff --git a/include/net/netfilter/nf_conntrack_zones.h b/include/net/netfilter/nf_conntrack_zones.h new file mode 100644 index 000000000000..0bbb2bd51e89 --- /dev/null +++ b/include/net/netfilter/nf_conntrack_zones.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef _NF_CONNTRACK_ZONES_H | ||
| 2 | #define _NF_CONNTRACK_ZONES_H | ||
| 3 | |||
| 4 | #include <net/netfilter/nf_conntrack_extend.h> | ||
| 5 | |||
| 6 | #define NF_CT_DEFAULT_ZONE 0 | ||
| 7 | |||
| 8 | struct nf_conntrack_zone { | ||
| 9 | u16 id; | ||
| 10 | }; | ||
| 11 | |||
| 12 | static inline u16 nf_ct_zone(const struct nf_conn *ct) | ||
| 13 | { | ||
| 14 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 15 | struct nf_conntrack_zone *nf_ct_zone; | ||
| 16 | nf_ct_zone = nf_ct_ext_find(ct, NF_CT_EXT_ZONE); | ||
| 17 | if (nf_ct_zone) | ||
| 18 | return nf_ct_zone->id; | ||
| 19 | #endif | ||
| 20 | return NF_CT_DEFAULT_ZONE; | ||
| 21 | } | ||
| 22 | |||
| 23 | #endif /* _NF_CONNTRACK_ZONES_H */ | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index d1ea38a7c490..2bb1f87051c4 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <net/netfilter/nf_conntrack_helper.h> | 22 | #include <net/netfilter/nf_conntrack_helper.h> |
| 23 | #include <net/netfilter/nf_conntrack_l4proto.h> | 23 | #include <net/netfilter/nf_conntrack_l4proto.h> |
| 24 | #include <net/netfilter/nf_conntrack_l3proto.h> | 24 | #include <net/netfilter/nf_conntrack_l3proto.h> |
| 25 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 25 | #include <net/netfilter/nf_conntrack_core.h> | 26 | #include <net/netfilter/nf_conntrack_core.h> |
| 26 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> | 27 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> |
| 27 | #include <net/netfilter/nf_nat_helper.h> | 28 | #include <net/netfilter/nf_nat_helper.h> |
| @@ -266,7 +267,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) | |||
| 266 | return -EINVAL; | 267 | return -EINVAL; |
| 267 | } | 268 | } |
| 268 | 269 | ||
| 269 | h = nf_conntrack_find_get(sock_net(sk), &tuple); | 270 | h = nf_conntrack_find_get(sock_net(sk), NF_CT_DEFAULT_ZONE, &tuple); |
| 270 | if (h) { | 271 | if (h) { |
| 271 | struct sockaddr_in sin; | 272 | struct sockaddr_in sin; |
| 272 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); | 273 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 327826a968a8..7404bde95994 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <net/netfilter/nf_conntrack_tuple.h> | 18 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 19 | #include <net/netfilter/nf_conntrack_l4proto.h> | 19 | #include <net/netfilter/nf_conntrack_l4proto.h> |
| 20 | #include <net/netfilter/nf_conntrack_core.h> | 20 | #include <net/netfilter/nf_conntrack_core.h> |
| 21 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 21 | #include <net/netfilter/nf_log.h> | 22 | #include <net/netfilter/nf_log.h> |
| 22 | 23 | ||
| 23 | static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ; | 24 | static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ; |
| @@ -114,13 +115,14 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
| 114 | 115 | ||
| 115 | /* Returns conntrack if it dealt with ICMP, and filled in skb fields */ | 116 | /* Returns conntrack if it dealt with ICMP, and filled in skb fields */ |
| 116 | static int | 117 | static int |
| 117 | icmp_error_message(struct net *net, struct sk_buff *skb, | 118 | icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, |
| 118 | enum ip_conntrack_info *ctinfo, | 119 | enum ip_conntrack_info *ctinfo, |
| 119 | unsigned int hooknum) | 120 | unsigned int hooknum) |
| 120 | { | 121 | { |
| 121 | struct nf_conntrack_tuple innertuple, origtuple; | 122 | struct nf_conntrack_tuple innertuple, origtuple; |
| 122 | const struct nf_conntrack_l4proto *innerproto; | 123 | const struct nf_conntrack_l4proto *innerproto; |
| 123 | const struct nf_conntrack_tuple_hash *h; | 124 | const struct nf_conntrack_tuple_hash *h; |
| 125 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; | ||
| 124 | 126 | ||
| 125 | NF_CT_ASSERT(skb->nfct == NULL); | 127 | NF_CT_ASSERT(skb->nfct == NULL); |
| 126 | 128 | ||
| @@ -146,7 +148,7 @@ icmp_error_message(struct net *net, struct sk_buff *skb, | |||
| 146 | 148 | ||
| 147 | *ctinfo = IP_CT_RELATED; | 149 | *ctinfo = IP_CT_RELATED; |
| 148 | 150 | ||
| 149 | h = nf_conntrack_find_get(net, &innertuple); | 151 | h = nf_conntrack_find_get(net, zone, &innertuple); |
| 150 | if (!h) { | 152 | if (!h) { |
| 151 | pr_debug("icmp_error_message: no match\n"); | 153 | pr_debug("icmp_error_message: no match\n"); |
| 152 | return -NF_ACCEPT; | 154 | return -NF_ACCEPT; |
| @@ -209,7 +211,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, | |||
| 209 | icmph->type != ICMP_REDIRECT) | 211 | icmph->type != ICMP_REDIRECT) |
| 210 | return NF_ACCEPT; | 212 | return NF_ACCEPT; |
| 211 | 213 | ||
| 212 | return icmp_error_message(net, skb, ctinfo, hooknum); | 214 | return icmp_error_message(net, tmpl, skb, ctinfo, hooknum); |
| 213 | } | 215 | } |
| 214 | 216 | ||
| 215 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 217 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index f6f46686cbc0..d498a704d456 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | #include <linux/netfilter_bridge.h> | 17 | #include <linux/netfilter_bridge.h> |
| 18 | #include <linux/netfilter_ipv4.h> | 18 | #include <linux/netfilter_ipv4.h> |
| 19 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 19 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> | 20 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> |
| 20 | #include <net/netfilter/nf_conntrack.h> | 21 | #include <net/netfilter/nf_conntrack.h> |
| 21 | 22 | ||
| @@ -39,15 +40,20 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) | |||
| 39 | static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, | 40 | static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, |
| 40 | struct sk_buff *skb) | 41 | struct sk_buff *skb) |
| 41 | { | 42 | { |
| 43 | u16 zone = NF_CT_DEFAULT_ZONE; | ||
| 44 | |||
| 45 | if (skb->nfct) | ||
| 46 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); | ||
| 47 | |||
| 42 | #ifdef CONFIG_BRIDGE_NETFILTER | 48 | #ifdef CONFIG_BRIDGE_NETFILTER |
| 43 | if (skb->nf_bridge && | 49 | if (skb->nf_bridge && |
| 44 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) | 50 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) |
| 45 | return IP_DEFRAG_CONNTRACK_BRIDGE_IN; | 51 | return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone; |
| 46 | #endif | 52 | #endif |
| 47 | if (hooknum == NF_INET_PRE_ROUTING) | 53 | if (hooknum == NF_INET_PRE_ROUTING) |
| 48 | return IP_DEFRAG_CONNTRACK_IN; | 54 | return IP_DEFRAG_CONNTRACK_IN + zone; |
| 49 | else | 55 | else |
| 50 | return IP_DEFRAG_CONNTRACK_OUT; | 56 | return IP_DEFRAG_CONNTRACK_OUT + zone; |
| 51 | } | 57 | } |
| 52 | 58 | ||
| 53 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, | 59 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 26066a2327ad..4595281c2863 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <net/netfilter/nf_conntrack_helper.h> | 30 | #include <net/netfilter/nf_conntrack_helper.h> |
| 31 | #include <net/netfilter/nf_conntrack_l3proto.h> | 31 | #include <net/netfilter/nf_conntrack_l3proto.h> |
| 32 | #include <net/netfilter/nf_conntrack_l4proto.h> | 32 | #include <net/netfilter/nf_conntrack_l4proto.h> |
| 33 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 33 | 34 | ||
| 34 | static DEFINE_SPINLOCK(nf_nat_lock); | 35 | static DEFINE_SPINLOCK(nf_nat_lock); |
| 35 | 36 | ||
| @@ -69,13 +70,14 @@ EXPORT_SYMBOL_GPL(nf_nat_proto_put); | |||
| 69 | 70 | ||
| 70 | /* We keep an extra hash for each conntrack, for fast searching. */ | 71 | /* We keep an extra hash for each conntrack, for fast searching. */ |
| 71 | static inline unsigned int | 72 | static inline unsigned int |
| 72 | hash_by_src(const struct net *net, const struct nf_conntrack_tuple *tuple) | 73 | hash_by_src(const struct net *net, u16 zone, |
| 74 | const struct nf_conntrack_tuple *tuple) | ||
| 73 | { | 75 | { |
| 74 | unsigned int hash; | 76 | unsigned int hash; |
| 75 | 77 | ||
| 76 | /* Original src, to ensure we map it consistently if poss. */ | 78 | /* Original src, to ensure we map it consistently if poss. */ |
| 77 | hash = jhash_3words((__force u32)tuple->src.u3.ip, | 79 | hash = jhash_3words((__force u32)tuple->src.u3.ip, |
| 78 | (__force u32)tuple->src.u.all, | 80 | (__force u32)tuple->src.u.all ^ zone, |
| 79 | tuple->dst.protonum, 0); | 81 | tuple->dst.protonum, 0); |
| 80 | return ((u64)hash * net->ipv4.nat_htable_size) >> 32; | 82 | return ((u64)hash * net->ipv4.nat_htable_size) >> 32; |
| 81 | } | 83 | } |
| @@ -139,12 +141,12 @@ same_src(const struct nf_conn *ct, | |||
| 139 | 141 | ||
| 140 | /* Only called for SRC manip */ | 142 | /* Only called for SRC manip */ |
| 141 | static int | 143 | static int |
| 142 | find_appropriate_src(struct net *net, | 144 | find_appropriate_src(struct net *net, u16 zone, |
| 143 | const struct nf_conntrack_tuple *tuple, | 145 | const struct nf_conntrack_tuple *tuple, |
| 144 | struct nf_conntrack_tuple *result, | 146 | struct nf_conntrack_tuple *result, |
| 145 | const struct nf_nat_range *range) | 147 | const struct nf_nat_range *range) |
| 146 | { | 148 | { |
| 147 | unsigned int h = hash_by_src(net, tuple); | 149 | unsigned int h = hash_by_src(net, zone, tuple); |
| 148 | const struct nf_conn_nat *nat; | 150 | const struct nf_conn_nat *nat; |
| 149 | const struct nf_conn *ct; | 151 | const struct nf_conn *ct; |
| 150 | const struct hlist_node *n; | 152 | const struct hlist_node *n; |
| @@ -152,7 +154,7 @@ find_appropriate_src(struct net *net, | |||
| 152 | rcu_read_lock(); | 154 | rcu_read_lock(); |
| 153 | hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) { | 155 | hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) { |
| 154 | ct = nat->ct; | 156 | ct = nat->ct; |
| 155 | if (same_src(ct, tuple)) { | 157 | if (same_src(ct, tuple) && nf_ct_zone(ct) == zone) { |
| 156 | /* Copy source part from reply tuple. */ | 158 | /* Copy source part from reply tuple. */ |
| 157 | nf_ct_invert_tuplepr(result, | 159 | nf_ct_invert_tuplepr(result, |
| 158 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 160 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
| @@ -175,7 +177,7 @@ find_appropriate_src(struct net *net, | |||
| 175 | the ip with the lowest src-ip/dst-ip/proto usage. | 177 | the ip with the lowest src-ip/dst-ip/proto usage. |
| 176 | */ | 178 | */ |
| 177 | static void | 179 | static void |
| 178 | find_best_ips_proto(struct nf_conntrack_tuple *tuple, | 180 | find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, |
| 179 | const struct nf_nat_range *range, | 181 | const struct nf_nat_range *range, |
| 180 | const struct nf_conn *ct, | 182 | const struct nf_conn *ct, |
| 181 | enum nf_nat_manip_type maniptype) | 183 | enum nf_nat_manip_type maniptype) |
| @@ -209,7 +211,7 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple, | |||
| 209 | maxip = ntohl(range->max_ip); | 211 | maxip = ntohl(range->max_ip); |
| 210 | j = jhash_2words((__force u32)tuple->src.u3.ip, | 212 | j = jhash_2words((__force u32)tuple->src.u3.ip, |
| 211 | range->flags & IP_NAT_RANGE_PERSISTENT ? | 213 | range->flags & IP_NAT_RANGE_PERSISTENT ? |
| 212 | 0 : (__force u32)tuple->dst.u3.ip, 0); | 214 | 0 : (__force u32)tuple->dst.u3.ip ^ zone, 0); |
| 213 | j = ((u64)j * (maxip - minip + 1)) >> 32; | 215 | j = ((u64)j * (maxip - minip + 1)) >> 32; |
| 214 | *var_ipp = htonl(minip + j); | 216 | *var_ipp = htonl(minip + j); |
| 215 | } | 217 | } |
| @@ -229,6 +231,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 229 | { | 231 | { |
| 230 | struct net *net = nf_ct_net(ct); | 232 | struct net *net = nf_ct_net(ct); |
| 231 | const struct nf_nat_protocol *proto; | 233 | const struct nf_nat_protocol *proto; |
| 234 | u16 zone = nf_ct_zone(ct); | ||
| 232 | 235 | ||
| 233 | /* 1) If this srcip/proto/src-proto-part is currently mapped, | 236 | /* 1) If this srcip/proto/src-proto-part is currently mapped, |
| 234 | and that same mapping gives a unique tuple within the given | 237 | and that same mapping gives a unique tuple within the given |
| @@ -239,7 +242,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 239 | manips not an issue. */ | 242 | manips not an issue. */ |
| 240 | if (maniptype == IP_NAT_MANIP_SRC && | 243 | if (maniptype == IP_NAT_MANIP_SRC && |
| 241 | !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { | 244 | !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { |
| 242 | if (find_appropriate_src(net, orig_tuple, tuple, range)) { | 245 | if (find_appropriate_src(net, zone, orig_tuple, tuple, range)) { |
| 243 | pr_debug("get_unique_tuple: Found current src map\n"); | 246 | pr_debug("get_unique_tuple: Found current src map\n"); |
| 244 | if (!nf_nat_used_tuple(tuple, ct)) | 247 | if (!nf_nat_used_tuple(tuple, ct)) |
| 245 | return; | 248 | return; |
| @@ -249,7 +252,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 249 | /* 2) Select the least-used IP/proto combination in the given | 252 | /* 2) Select the least-used IP/proto combination in the given |
| 250 | range. */ | 253 | range. */ |
| 251 | *tuple = *orig_tuple; | 254 | *tuple = *orig_tuple; |
| 252 | find_best_ips_proto(tuple, range, ct, maniptype); | 255 | find_best_ips_proto(zone, tuple, range, ct, maniptype); |
| 253 | 256 | ||
| 254 | /* 3) The per-protocol part of the manip is made to map into | 257 | /* 3) The per-protocol part of the manip is made to map into |
| 255 | the range to make a unique tuple. */ | 258 | the range to make a unique tuple. */ |
| @@ -327,7 +330,8 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
| 327 | if (have_to_hash) { | 330 | if (have_to_hash) { |
| 328 | unsigned int srchash; | 331 | unsigned int srchash; |
| 329 | 332 | ||
| 330 | srchash = hash_by_src(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 333 | srchash = hash_by_src(net, nf_ct_zone(ct), |
| 334 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | ||
| 331 | spin_lock_bh(&nf_nat_lock); | 335 | spin_lock_bh(&nf_nat_lock); |
| 332 | /* nf_conntrack_alter_reply might re-allocate exntension aera */ | 336 | /* nf_conntrack_alter_reply might re-allocate exntension aera */ |
| 333 | nat = nfct_nat(ct); | 337 | nat = nfct_nat(ct); |
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index 9eb171056c63..4c060038d29f 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <net/netfilter/nf_nat_rule.h> | 25 | #include <net/netfilter/nf_nat_rule.h> |
| 26 | #include <net/netfilter/nf_conntrack_helper.h> | 26 | #include <net/netfilter/nf_conntrack_helper.h> |
| 27 | #include <net/netfilter/nf_conntrack_expect.h> | 27 | #include <net/netfilter/nf_conntrack_expect.h> |
| 28 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 28 | #include <linux/netfilter/nf_conntrack_proto_gre.h> | 29 | #include <linux/netfilter/nf_conntrack_proto_gre.h> |
| 29 | #include <linux/netfilter/nf_conntrack_pptp.h> | 30 | #include <linux/netfilter/nf_conntrack_pptp.h> |
| 30 | 31 | ||
| @@ -74,7 +75,7 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
| 74 | 75 | ||
| 75 | pr_debug("trying to unexpect other dir: "); | 76 | pr_debug("trying to unexpect other dir: "); |
| 76 | nf_ct_dump_tuple_ip(&t); | 77 | nf_ct_dump_tuple_ip(&t); |
| 77 | other_exp = nf_ct_expect_find_get(net, &t); | 78 | other_exp = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); |
| 78 | if (other_exp) { | 79 | if (other_exp) { |
| 79 | nf_ct_unexpect_related(other_exp); | 80 | nf_ct_unexpect_related(other_exp); |
| 80 | nf_ct_expect_put(other_exp); | 81 | nf_ct_expect_put(other_exp); |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 55ce22e5de49..996c3f41fecd 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <net/netfilter/nf_conntrack_l4proto.h> | 27 | #include <net/netfilter/nf_conntrack_l4proto.h> |
| 28 | #include <net/netfilter/nf_conntrack_l3proto.h> | 28 | #include <net/netfilter/nf_conntrack_l3proto.h> |
| 29 | #include <net/netfilter/nf_conntrack_core.h> | 29 | #include <net/netfilter/nf_conntrack_core.h> |
| 30 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 30 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | 31 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
| 31 | #include <net/netfilter/nf_log.h> | 32 | #include <net/netfilter/nf_log.h> |
| 32 | 33 | ||
| @@ -191,15 +192,20 @@ out: | |||
| 191 | static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, | 192 | static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, |
| 192 | struct sk_buff *skb) | 193 | struct sk_buff *skb) |
| 193 | { | 194 | { |
| 195 | u16 zone = NF_CT_DEFAULT_ZONE; | ||
| 196 | |||
| 197 | if (skb->nfct) | ||
| 198 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); | ||
| 199 | |||
| 194 | #ifdef CONFIG_BRIDGE_NETFILTER | 200 | #ifdef CONFIG_BRIDGE_NETFILTER |
| 195 | if (skb->nf_bridge && | 201 | if (skb->nf_bridge && |
| 196 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) | 202 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) |
| 197 | return IP6_DEFRAG_CONNTRACK_BRIDGE_IN; | 203 | return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone; |
| 198 | #endif | 204 | #endif |
| 199 | if (hooknum == NF_INET_PRE_ROUTING) | 205 | if (hooknum == NF_INET_PRE_ROUTING) |
| 200 | return IP6_DEFRAG_CONNTRACK_IN; | 206 | return IP6_DEFRAG_CONNTRACK_IN + zone; |
| 201 | else | 207 | else |
| 202 | return IP6_DEFRAG_CONNTRACK_OUT; | 208 | return IP6_DEFRAG_CONNTRACK_OUT + zone; |
| 203 | 209 | ||
| 204 | } | 210 | } |
| 205 | 211 | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index d772dc21857f..9be81776415e 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <net/netfilter/nf_conntrack_tuple.h> | 23 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 24 | #include <net/netfilter/nf_conntrack_l4proto.h> | 24 | #include <net/netfilter/nf_conntrack_l4proto.h> |
| 25 | #include <net/netfilter/nf_conntrack_core.h> | 25 | #include <net/netfilter/nf_conntrack_core.h> |
| 26 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 26 | #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> | 27 | #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> |
| 27 | #include <net/netfilter/nf_log.h> | 28 | #include <net/netfilter/nf_log.h> |
| 28 | 29 | ||
| @@ -128,7 +129,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
| 128 | } | 129 | } |
| 129 | 130 | ||
| 130 | static int | 131 | static int |
| 131 | icmpv6_error_message(struct net *net, | 132 | icmpv6_error_message(struct net *net, struct nf_conn *tmpl, |
| 132 | struct sk_buff *skb, | 133 | struct sk_buff *skb, |
| 133 | unsigned int icmp6off, | 134 | unsigned int icmp6off, |
| 134 | enum ip_conntrack_info *ctinfo, | 135 | enum ip_conntrack_info *ctinfo, |
| @@ -137,6 +138,7 @@ icmpv6_error_message(struct net *net, | |||
| 137 | struct nf_conntrack_tuple intuple, origtuple; | 138 | struct nf_conntrack_tuple intuple, origtuple; |
| 138 | const struct nf_conntrack_tuple_hash *h; | 139 | const struct nf_conntrack_tuple_hash *h; |
| 139 | const struct nf_conntrack_l4proto *inproto; | 140 | const struct nf_conntrack_l4proto *inproto; |
| 141 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; | ||
| 140 | 142 | ||
| 141 | NF_CT_ASSERT(skb->nfct == NULL); | 143 | NF_CT_ASSERT(skb->nfct == NULL); |
| 142 | 144 | ||
| @@ -163,7 +165,7 @@ icmpv6_error_message(struct net *net, | |||
| 163 | 165 | ||
| 164 | *ctinfo = IP_CT_RELATED; | 166 | *ctinfo = IP_CT_RELATED; |
| 165 | 167 | ||
| 166 | h = nf_conntrack_find_get(net, &intuple); | 168 | h = nf_conntrack_find_get(net, zone, &intuple); |
| 167 | if (!h) { | 169 | if (!h) { |
| 168 | pr_debug("icmpv6_error: no match\n"); | 170 | pr_debug("icmpv6_error: no match\n"); |
| 169 | return -NF_ACCEPT; | 171 | return -NF_ACCEPT; |
| @@ -216,7 +218,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, | |||
| 216 | if (icmp6h->icmp6_type >= 128) | 218 | if (icmp6h->icmp6_type >= 128) |
| 217 | return NF_ACCEPT; | 219 | return NF_ACCEPT; |
| 218 | 220 | ||
| 219 | return icmpv6_error_message(net, skb, dataoff, ctinfo, hooknum); | 221 | return icmpv6_error_message(net, tmpl, skb, dataoff, ctinfo, hooknum); |
| 220 | } | 222 | } |
| 221 | 223 | ||
| 222 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 224 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 4469d45261f4..18d77b5c351a 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -83,6 +83,19 @@ config NF_CONNTRACK_SECMARK | |||
| 83 | 83 | ||
| 84 | If unsure, say 'N'. | 84 | If unsure, say 'N'. |
| 85 | 85 | ||
| 86 | config NF_CONNTRACK_ZONES | ||
| 87 | bool 'Connection tracking zones' | ||
| 88 | depends on NETFILTER_ADVANCED | ||
| 89 | depends on NETFILTER_XT_TARGET_CT | ||
| 90 | help | ||
| 91 | This option enables support for connection tracking zones. | ||
| 92 | Normally, each connection needs to have a unique system wide | ||
| 93 | identity. Connection tracking zones allow to have multiple | ||
| 94 | connections using the same identity, as long as they are | ||
| 95 | contained in different zones. | ||
| 96 | |||
| 97 | If unsure, say `N'. | ||
| 98 | |||
| 86 | config NF_CONNTRACK_EVENTS | 99 | config NF_CONNTRACK_EVENTS |
| 87 | bool "Connection tracking events" | 100 | bool "Connection tracking events" |
| 88 | depends on NETFILTER_ADVANCED | 101 | depends on NETFILTER_ADVANCED |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 65351ed5d815..0c9bbe93cc16 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <net/netfilter/nf_conntrack_extend.h> | 42 | #include <net/netfilter/nf_conntrack_extend.h> |
| 43 | #include <net/netfilter/nf_conntrack_acct.h> | 43 | #include <net/netfilter/nf_conntrack_acct.h> |
| 44 | #include <net/netfilter/nf_conntrack_ecache.h> | 44 | #include <net/netfilter/nf_conntrack_ecache.h> |
| 45 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 45 | #include <net/netfilter/nf_nat.h> | 46 | #include <net/netfilter/nf_nat.h> |
| 46 | #include <net/netfilter/nf_nat_core.h> | 47 | #include <net/netfilter/nf_nat_core.h> |
| 47 | 48 | ||
| @@ -68,7 +69,7 @@ static int nf_conntrack_hash_rnd_initted; | |||
| 68 | static unsigned int nf_conntrack_hash_rnd; | 69 | static unsigned int nf_conntrack_hash_rnd; |
| 69 | 70 | ||
| 70 | static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, | 71 | static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, |
| 71 | unsigned int size, unsigned int rnd) | 72 | u16 zone, unsigned int size, unsigned int rnd) |
| 72 | { | 73 | { |
| 73 | unsigned int n; | 74 | unsigned int n; |
| 74 | u_int32_t h; | 75 | u_int32_t h; |
| @@ -79,16 +80,16 @@ static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, | |||
| 79 | */ | 80 | */ |
| 80 | n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32); | 81 | n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32); |
| 81 | h = jhash2((u32 *)tuple, n, | 82 | h = jhash2((u32 *)tuple, n, |
| 82 | rnd ^ (((__force __u16)tuple->dst.u.all << 16) | | 83 | zone ^ rnd ^ (((__force __u16)tuple->dst.u.all << 16) | |
| 83 | tuple->dst.protonum)); | 84 | tuple->dst.protonum)); |
| 84 | 85 | ||
| 85 | return ((u64)h * size) >> 32; | 86 | return ((u64)h * size) >> 32; |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | static inline u_int32_t hash_conntrack(const struct net *net, | 89 | static inline u_int32_t hash_conntrack(const struct net *net, u16 zone, |
| 89 | const struct nf_conntrack_tuple *tuple) | 90 | const struct nf_conntrack_tuple *tuple) |
| 90 | { | 91 | { |
| 91 | return __hash_conntrack(tuple, net->ct.htable_size, | 92 | return __hash_conntrack(tuple, zone, net->ct.htable_size, |
| 92 | nf_conntrack_hash_rnd); | 93 | nf_conntrack_hash_rnd); |
| 93 | } | 94 | } |
| 94 | 95 | ||
| @@ -292,11 +293,12 @@ static void death_by_timeout(unsigned long ul_conntrack) | |||
| 292 | * - Caller must lock nf_conntrack_lock before calling this function | 293 | * - Caller must lock nf_conntrack_lock before calling this function |
| 293 | */ | 294 | */ |
| 294 | struct nf_conntrack_tuple_hash * | 295 | struct nf_conntrack_tuple_hash * |
| 295 | __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) | 296 | __nf_conntrack_find(struct net *net, u16 zone, |
| 297 | const struct nf_conntrack_tuple *tuple) | ||
| 296 | { | 298 | { |
| 297 | struct nf_conntrack_tuple_hash *h; | 299 | struct nf_conntrack_tuple_hash *h; |
| 298 | struct hlist_nulls_node *n; | 300 | struct hlist_nulls_node *n; |
| 299 | unsigned int hash = hash_conntrack(net, tuple); | 301 | unsigned int hash = hash_conntrack(net, zone, tuple); |
| 300 | 302 | ||
| 301 | /* Disable BHs the entire time since we normally need to disable them | 303 | /* Disable BHs the entire time since we normally need to disable them |
| 302 | * at least once for the stats anyway. | 304 | * at least once for the stats anyway. |
| @@ -304,7 +306,8 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) | |||
| 304 | local_bh_disable(); | 306 | local_bh_disable(); |
| 305 | begin: | 307 | begin: |
| 306 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { | 308 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { |
| 307 | if (nf_ct_tuple_equal(tuple, &h->tuple)) { | 309 | if (nf_ct_tuple_equal(tuple, &h->tuple) && |
| 310 | nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) { | ||
| 308 | NF_CT_STAT_INC(net, found); | 311 | NF_CT_STAT_INC(net, found); |
| 309 | local_bh_enable(); | 312 | local_bh_enable(); |
| 310 | return h; | 313 | return h; |
| @@ -326,21 +329,23 @@ EXPORT_SYMBOL_GPL(__nf_conntrack_find); | |||
| 326 | 329 | ||
| 327 | /* Find a connection corresponding to a tuple. */ | 330 | /* Find a connection corresponding to a tuple. */ |
| 328 | struct nf_conntrack_tuple_hash * | 331 | struct nf_conntrack_tuple_hash * |
| 329 | nf_conntrack_find_get(struct net *net, const struct nf_conntrack_tuple *tuple) | 332 | nf_conntrack_find_get(struct net *net, u16 zone, |
| 333 | const struct nf_conntrack_tuple *tuple) | ||
| 330 | { | 334 | { |
| 331 | struct nf_conntrack_tuple_hash *h; | 335 | struct nf_conntrack_tuple_hash *h; |
| 332 | struct nf_conn *ct; | 336 | struct nf_conn *ct; |
| 333 | 337 | ||
| 334 | rcu_read_lock(); | 338 | rcu_read_lock(); |
| 335 | begin: | 339 | begin: |
| 336 | h = __nf_conntrack_find(net, tuple); | 340 | h = __nf_conntrack_find(net, zone, tuple); |
| 337 | if (h) { | 341 | if (h) { |
| 338 | ct = nf_ct_tuplehash_to_ctrack(h); | 342 | ct = nf_ct_tuplehash_to_ctrack(h); |
| 339 | if (unlikely(nf_ct_is_dying(ct) || | 343 | if (unlikely(nf_ct_is_dying(ct) || |
| 340 | !atomic_inc_not_zero(&ct->ct_general.use))) | 344 | !atomic_inc_not_zero(&ct->ct_general.use))) |
| 341 | h = NULL; | 345 | h = NULL; |
| 342 | else { | 346 | else { |
| 343 | if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple))) { | 347 | if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) || |
| 348 | nf_ct_zone(ct) != zone)) { | ||
| 344 | nf_ct_put(ct); | 349 | nf_ct_put(ct); |
| 345 | goto begin; | 350 | goto begin; |
| 346 | } | 351 | } |
| @@ -368,9 +373,11 @@ void nf_conntrack_hash_insert(struct nf_conn *ct) | |||
| 368 | { | 373 | { |
| 369 | struct net *net = nf_ct_net(ct); | 374 | struct net *net = nf_ct_net(ct); |
| 370 | unsigned int hash, repl_hash; | 375 | unsigned int hash, repl_hash; |
| 376 | u16 zone; | ||
| 371 | 377 | ||
| 372 | hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 378 | zone = nf_ct_zone(ct); |
| 373 | repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 379 | hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
| 380 | repl_hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | ||
| 374 | 381 | ||
| 375 | __nf_conntrack_hash_insert(ct, hash, repl_hash); | 382 | __nf_conntrack_hash_insert(ct, hash, repl_hash); |
| 376 | } | 383 | } |
| @@ -387,6 +394,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 387 | struct hlist_nulls_node *n; | 394 | struct hlist_nulls_node *n; |
| 388 | enum ip_conntrack_info ctinfo; | 395 | enum ip_conntrack_info ctinfo; |
| 389 | struct net *net; | 396 | struct net *net; |
| 397 | u16 zone; | ||
| 390 | 398 | ||
| 391 | ct = nf_ct_get(skb, &ctinfo); | 399 | ct = nf_ct_get(skb, &ctinfo); |
| 392 | net = nf_ct_net(ct); | 400 | net = nf_ct_net(ct); |
| @@ -398,8 +406,9 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 398 | if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) | 406 | if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) |
| 399 | return NF_ACCEPT; | 407 | return NF_ACCEPT; |
| 400 | 408 | ||
| 401 | hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 409 | zone = nf_ct_zone(ct); |
| 402 | repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 410 | hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
| 411 | repl_hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | ||
| 403 | 412 | ||
| 404 | /* We're not in hash table, and we refuse to set up related | 413 | /* We're not in hash table, and we refuse to set up related |
| 405 | connections for unconfirmed conns. But packet copies and | 414 | connections for unconfirmed conns. But packet copies and |
| @@ -418,11 +427,13 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 418 | not in the hash. If there is, we lost race. */ | 427 | not in the hash. If there is, we lost race. */ |
| 419 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) | 428 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) |
| 420 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | 429 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |
| 421 | &h->tuple)) | 430 | &h->tuple) && |
| 431 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) | ||
| 422 | goto out; | 432 | goto out; |
| 423 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode) | 433 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode) |
| 424 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, | 434 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
| 425 | &h->tuple)) | 435 | &h->tuple) && |
| 436 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) | ||
| 426 | goto out; | 437 | goto out; |
| 427 | 438 | ||
| 428 | /* Remove from unconfirmed list */ | 439 | /* Remove from unconfirmed list */ |
| @@ -469,15 +480,19 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, | |||
| 469 | struct net *net = nf_ct_net(ignored_conntrack); | 480 | struct net *net = nf_ct_net(ignored_conntrack); |
| 470 | struct nf_conntrack_tuple_hash *h; | 481 | struct nf_conntrack_tuple_hash *h; |
| 471 | struct hlist_nulls_node *n; | 482 | struct hlist_nulls_node *n; |
| 472 | unsigned int hash = hash_conntrack(net, tuple); | 483 | struct nf_conn *ct; |
| 484 | u16 zone = nf_ct_zone(ignored_conntrack); | ||
| 485 | unsigned int hash = hash_conntrack(net, zone, tuple); | ||
| 473 | 486 | ||
| 474 | /* Disable BHs the entire time since we need to disable them at | 487 | /* Disable BHs the entire time since we need to disable them at |
| 475 | * least once for the stats anyway. | 488 | * least once for the stats anyway. |
| 476 | */ | 489 | */ |
| 477 | rcu_read_lock_bh(); | 490 | rcu_read_lock_bh(); |
| 478 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { | 491 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { |
| 479 | if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && | 492 | ct = nf_ct_tuplehash_to_ctrack(h); |
| 480 | nf_ct_tuple_equal(tuple, &h->tuple)) { | 493 | if (ct != ignored_conntrack && |
| 494 | nf_ct_tuple_equal(tuple, &h->tuple) && | ||
| 495 | nf_ct_zone(ct) == zone) { | ||
| 481 | NF_CT_STAT_INC(net, found); | 496 | NF_CT_STAT_INC(net, found); |
| 482 | rcu_read_unlock_bh(); | 497 | rcu_read_unlock_bh(); |
| 483 | return 1; | 498 | return 1; |
| @@ -540,7 +555,7 @@ static noinline int early_drop(struct net *net, unsigned int hash) | |||
| 540 | return dropped; | 555 | return dropped; |
| 541 | } | 556 | } |
| 542 | 557 | ||
| 543 | struct nf_conn *nf_conntrack_alloc(struct net *net, | 558 | struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone, |
| 544 | const struct nf_conntrack_tuple *orig, | 559 | const struct nf_conntrack_tuple *orig, |
| 545 | const struct nf_conntrack_tuple *repl, | 560 | const struct nf_conntrack_tuple *repl, |
| 546 | gfp_t gfp) | 561 | gfp_t gfp) |
| @@ -558,7 +573,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, | |||
| 558 | 573 | ||
| 559 | if (nf_conntrack_max && | 574 | if (nf_conntrack_max && |
| 560 | unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) { | 575 | unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) { |
| 561 | unsigned int hash = hash_conntrack(net, orig); | 576 | unsigned int hash = hash_conntrack(net, zone, orig); |
| 562 | if (!early_drop(net, hash)) { | 577 | if (!early_drop(net, hash)) { |
| 563 | atomic_dec(&net->ct.count); | 578 | atomic_dec(&net->ct.count); |
| 564 | if (net_ratelimit()) | 579 | if (net_ratelimit()) |
| @@ -595,13 +610,28 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, | |||
| 595 | #ifdef CONFIG_NET_NS | 610 | #ifdef CONFIG_NET_NS |
| 596 | ct->ct_net = net; | 611 | ct->ct_net = net; |
| 597 | #endif | 612 | #endif |
| 598 | 613 | #ifdef CONFIG_NF_CONNTRACK_ZONES | |
| 614 | if (zone) { | ||
| 615 | struct nf_conntrack_zone *nf_ct_zone; | ||
| 616 | |||
| 617 | nf_ct_zone = nf_ct_ext_add(ct, NF_CT_EXT_ZONE, GFP_ATOMIC); | ||
| 618 | if (!nf_ct_zone) | ||
| 619 | goto out_free; | ||
| 620 | nf_ct_zone->id = zone; | ||
| 621 | } | ||
| 622 | #endif | ||
| 599 | /* | 623 | /* |
| 600 | * changes to lookup keys must be done before setting refcnt to 1 | 624 | * changes to lookup keys must be done before setting refcnt to 1 |
| 601 | */ | 625 | */ |
| 602 | smp_wmb(); | 626 | smp_wmb(); |
| 603 | atomic_set(&ct->ct_general.use, 1); | 627 | atomic_set(&ct->ct_general.use, 1); |
| 604 | return ct; | 628 | return ct; |
| 629 | |||
| 630 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 631 | out_free: | ||
| 632 | kmem_cache_free(net->ct.nf_conntrack_cachep, ct); | ||
| 633 | return ERR_PTR(-ENOMEM); | ||
| 634 | #endif | ||
| 605 | } | 635 | } |
| 606 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); | 636 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); |
| 607 | 637 | ||
| @@ -631,13 +661,14 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
| 631 | struct nf_conntrack_tuple repl_tuple; | 661 | struct nf_conntrack_tuple repl_tuple; |
| 632 | struct nf_conntrack_ecache *ecache; | 662 | struct nf_conntrack_ecache *ecache; |
| 633 | struct nf_conntrack_expect *exp; | 663 | struct nf_conntrack_expect *exp; |
| 664 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; | ||
| 634 | 665 | ||
| 635 | if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { | 666 | if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { |
| 636 | pr_debug("Can't invert tuple.\n"); | 667 | pr_debug("Can't invert tuple.\n"); |
| 637 | return NULL; | 668 | return NULL; |
| 638 | } | 669 | } |
| 639 | 670 | ||
| 640 | ct = nf_conntrack_alloc(net, tuple, &repl_tuple, GFP_ATOMIC); | 671 | ct = nf_conntrack_alloc(net, zone, tuple, &repl_tuple, GFP_ATOMIC); |
| 641 | if (IS_ERR(ct)) { | 672 | if (IS_ERR(ct)) { |
| 642 | pr_debug("Can't allocate conntrack.\n"); | 673 | pr_debug("Can't allocate conntrack.\n"); |
| 643 | return (struct nf_conntrack_tuple_hash *)ct; | 674 | return (struct nf_conntrack_tuple_hash *)ct; |
| @@ -657,7 +688,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
| 657 | GFP_ATOMIC); | 688 | GFP_ATOMIC); |
| 658 | 689 | ||
| 659 | spin_lock_bh(&nf_conntrack_lock); | 690 | spin_lock_bh(&nf_conntrack_lock); |
| 660 | exp = nf_ct_find_expectation(net, tuple); | 691 | exp = nf_ct_find_expectation(net, zone, tuple); |
| 661 | if (exp) { | 692 | if (exp) { |
| 662 | pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", | 693 | pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", |
| 663 | ct, exp); | 694 | ct, exp); |
| @@ -713,6 +744,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, | |||
| 713 | struct nf_conntrack_tuple tuple; | 744 | struct nf_conntrack_tuple tuple; |
| 714 | struct nf_conntrack_tuple_hash *h; | 745 | struct nf_conntrack_tuple_hash *h; |
| 715 | struct nf_conn *ct; | 746 | struct nf_conn *ct; |
| 747 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; | ||
| 716 | 748 | ||
| 717 | if (!nf_ct_get_tuple(skb, skb_network_offset(skb), | 749 | if (!nf_ct_get_tuple(skb, skb_network_offset(skb), |
| 718 | dataoff, l3num, protonum, &tuple, l3proto, | 750 | dataoff, l3num, protonum, &tuple, l3proto, |
| @@ -722,7 +754,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, | |||
| 722 | } | 754 | } |
| 723 | 755 | ||
| 724 | /* look for tuple match */ | 756 | /* look for tuple match */ |
| 725 | h = nf_conntrack_find_get(net, &tuple); | 757 | h = nf_conntrack_find_get(net, zone, &tuple); |
| 726 | if (!h) { | 758 | if (!h) { |
| 727 | h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, | 759 | h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, |
| 728 | skb, dataoff); | 760 | skb, dataoff); |
| @@ -958,6 +990,14 @@ bool __nf_ct_kill_acct(struct nf_conn *ct, | |||
| 958 | } | 990 | } |
| 959 | EXPORT_SYMBOL_GPL(__nf_ct_kill_acct); | 991 | EXPORT_SYMBOL_GPL(__nf_ct_kill_acct); |
| 960 | 992 | ||
| 993 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 994 | static struct nf_ct_ext_type nf_ct_zone_extend __read_mostly = { | ||
| 995 | .len = sizeof(struct nf_conntrack_zone), | ||
| 996 | .align = __alignof__(struct nf_conntrack_zone), | ||
| 997 | .id = NF_CT_EXT_ZONE, | ||
| 998 | }; | ||
| 999 | #endif | ||
| 1000 | |||
| 961 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 1001 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 962 | 1002 | ||
| 963 | #include <linux/netfilter/nfnetlink.h> | 1003 | #include <linux/netfilter/nfnetlink.h> |
| @@ -1139,6 +1179,9 @@ static void nf_conntrack_cleanup_init_net(void) | |||
| 1139 | 1179 | ||
| 1140 | nf_conntrack_helper_fini(); | 1180 | nf_conntrack_helper_fini(); |
| 1141 | nf_conntrack_proto_fini(); | 1181 | nf_conntrack_proto_fini(); |
| 1182 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 1183 | nf_ct_extend_unregister(&nf_ct_zone_extend); | ||
| 1184 | #endif | ||
| 1142 | } | 1185 | } |
| 1143 | 1186 | ||
| 1144 | static void nf_conntrack_cleanup_net(struct net *net) | 1187 | static void nf_conntrack_cleanup_net(struct net *net) |
| @@ -1214,6 +1257,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) | |||
| 1214 | unsigned int hashsize, old_size; | 1257 | unsigned int hashsize, old_size; |
| 1215 | struct hlist_nulls_head *hash, *old_hash; | 1258 | struct hlist_nulls_head *hash, *old_hash; |
| 1216 | struct nf_conntrack_tuple_hash *h; | 1259 | struct nf_conntrack_tuple_hash *h; |
| 1260 | struct nf_conn *ct; | ||
| 1217 | 1261 | ||
| 1218 | if (current->nsproxy->net_ns != &init_net) | 1262 | if (current->nsproxy->net_ns != &init_net) |
| 1219 | return -EOPNOTSUPP; | 1263 | return -EOPNOTSUPP; |
| @@ -1240,8 +1284,10 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) | |||
| 1240 | while (!hlist_nulls_empty(&init_net.ct.hash[i])) { | 1284 | while (!hlist_nulls_empty(&init_net.ct.hash[i])) { |
| 1241 | h = hlist_nulls_entry(init_net.ct.hash[i].first, | 1285 | h = hlist_nulls_entry(init_net.ct.hash[i].first, |
| 1242 | struct nf_conntrack_tuple_hash, hnnode); | 1286 | struct nf_conntrack_tuple_hash, hnnode); |
| 1287 | ct = nf_ct_tuplehash_to_ctrack(h); | ||
| 1243 | hlist_nulls_del_rcu(&h->hnnode); | 1288 | hlist_nulls_del_rcu(&h->hnnode); |
| 1244 | bucket = __hash_conntrack(&h->tuple, hashsize, | 1289 | bucket = __hash_conntrack(&h->tuple, nf_ct_zone(ct), |
| 1290 | hashsize, | ||
| 1245 | nf_conntrack_hash_rnd); | 1291 | nf_conntrack_hash_rnd); |
| 1246 | hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); | 1292 | hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); |
| 1247 | } | 1293 | } |
| @@ -1299,6 +1345,11 @@ static int nf_conntrack_init_init_net(void) | |||
| 1299 | if (ret < 0) | 1345 | if (ret < 0) |
| 1300 | goto err_helper; | 1346 | goto err_helper; |
| 1301 | 1347 | ||
| 1348 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 1349 | ret = nf_ct_extend_register(&nf_ct_zone_extend); | ||
| 1350 | if (ret < 0) | ||
| 1351 | goto err_extend; | ||
| 1352 | #endif | ||
| 1302 | /* Set up fake conntrack: to never be deleted, not in any hashes */ | 1353 | /* Set up fake conntrack: to never be deleted, not in any hashes */ |
| 1303 | #ifdef CONFIG_NET_NS | 1354 | #ifdef CONFIG_NET_NS |
| 1304 | nf_conntrack_untracked.ct_net = &init_net; | 1355 | nf_conntrack_untracked.ct_net = &init_net; |
| @@ -1309,6 +1360,10 @@ static int nf_conntrack_init_init_net(void) | |||
| 1309 | 1360 | ||
| 1310 | return 0; | 1361 | return 0; |
| 1311 | 1362 | ||
| 1363 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 1364 | err_extend: | ||
| 1365 | nf_conntrack_helper_fini(); | ||
| 1366 | #endif | ||
| 1312 | err_helper: | 1367 | err_helper: |
| 1313 | nf_conntrack_proto_fini(); | 1368 | nf_conntrack_proto_fini(); |
| 1314 | err_proto: | 1369 | err_proto: |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 6182fb1b55de..acb29ccaa41f 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <net/netfilter/nf_conntrack_expect.h> | 27 | #include <net/netfilter/nf_conntrack_expect.h> |
| 28 | #include <net/netfilter/nf_conntrack_helper.h> | 28 | #include <net/netfilter/nf_conntrack_helper.h> |
| 29 | #include <net/netfilter/nf_conntrack_tuple.h> | 29 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 30 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 30 | 31 | ||
| 31 | unsigned int nf_ct_expect_hsize __read_mostly; | 32 | unsigned int nf_ct_expect_hsize __read_mostly; |
| 32 | EXPORT_SYMBOL_GPL(nf_ct_expect_hsize); | 33 | EXPORT_SYMBOL_GPL(nf_ct_expect_hsize); |
| @@ -84,7 +85,8 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple | |||
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | struct nf_conntrack_expect * | 87 | struct nf_conntrack_expect * |
| 87 | __nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple) | 88 | __nf_ct_expect_find(struct net *net, u16 zone, |
| 89 | const struct nf_conntrack_tuple *tuple) | ||
| 88 | { | 90 | { |
| 89 | struct nf_conntrack_expect *i; | 91 | struct nf_conntrack_expect *i; |
| 90 | struct hlist_node *n; | 92 | struct hlist_node *n; |
| @@ -95,7 +97,8 @@ __nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple) | |||
| 95 | 97 | ||
| 96 | h = nf_ct_expect_dst_hash(tuple); | 98 | h = nf_ct_expect_dst_hash(tuple); |
| 97 | hlist_for_each_entry_rcu(i, n, &net->ct.expect_hash[h], hnode) { | 99 | hlist_for_each_entry_rcu(i, n, &net->ct.expect_hash[h], hnode) { |
| 98 | if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) | 100 | if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) && |
| 101 | nf_ct_zone(i->master) == zone) | ||
| 99 | return i; | 102 | return i; |
| 100 | } | 103 | } |
| 101 | return NULL; | 104 | return NULL; |
| @@ -104,12 +107,13 @@ EXPORT_SYMBOL_GPL(__nf_ct_expect_find); | |||
| 104 | 107 | ||
| 105 | /* Just find a expectation corresponding to a tuple. */ | 108 | /* Just find a expectation corresponding to a tuple. */ |
| 106 | struct nf_conntrack_expect * | 109 | struct nf_conntrack_expect * |
| 107 | nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple) | 110 | nf_ct_expect_find_get(struct net *net, u16 zone, |
| 111 | const struct nf_conntrack_tuple *tuple) | ||
| 108 | { | 112 | { |
| 109 | struct nf_conntrack_expect *i; | 113 | struct nf_conntrack_expect *i; |
| 110 | 114 | ||
| 111 | rcu_read_lock(); | 115 | rcu_read_lock(); |
| 112 | i = __nf_ct_expect_find(net, tuple); | 116 | i = __nf_ct_expect_find(net, zone, tuple); |
| 113 | if (i && !atomic_inc_not_zero(&i->use)) | 117 | if (i && !atomic_inc_not_zero(&i->use)) |
| 114 | i = NULL; | 118 | i = NULL; |
| 115 | rcu_read_unlock(); | 119 | rcu_read_unlock(); |
| @@ -121,7 +125,8 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get); | |||
| 121 | /* If an expectation for this connection is found, it gets delete from | 125 | /* If an expectation for this connection is found, it gets delete from |
| 122 | * global list then returned. */ | 126 | * global list then returned. */ |
| 123 | struct nf_conntrack_expect * | 127 | struct nf_conntrack_expect * |
| 124 | nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple) | 128 | nf_ct_find_expectation(struct net *net, u16 zone, |
| 129 | const struct nf_conntrack_tuple *tuple) | ||
| 125 | { | 130 | { |
| 126 | struct nf_conntrack_expect *i, *exp = NULL; | 131 | struct nf_conntrack_expect *i, *exp = NULL; |
| 127 | struct hlist_node *n; | 132 | struct hlist_node *n; |
| @@ -133,7 +138,8 @@ nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple) | |||
| 133 | h = nf_ct_expect_dst_hash(tuple); | 138 | h = nf_ct_expect_dst_hash(tuple); |
| 134 | hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { | 139 | hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { |
| 135 | if (!(i->flags & NF_CT_EXPECT_INACTIVE) && | 140 | if (!(i->flags & NF_CT_EXPECT_INACTIVE) && |
| 136 | nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) { | 141 | nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) && |
| 142 | nf_ct_zone(i->master) == zone) { | ||
| 137 | exp = i; | 143 | exp = i; |
| 138 | break; | 144 | break; |
| 139 | } | 145 | } |
| @@ -204,7 +210,8 @@ static inline int expect_matches(const struct nf_conntrack_expect *a, | |||
| 204 | { | 210 | { |
| 205 | return a->master == b->master && a->class == b->class && | 211 | return a->master == b->master && a->class == b->class && |
| 206 | nf_ct_tuple_equal(&a->tuple, &b->tuple) && | 212 | nf_ct_tuple_equal(&a->tuple, &b->tuple) && |
| 207 | nf_ct_tuple_mask_equal(&a->mask, &b->mask); | 213 | nf_ct_tuple_mask_equal(&a->mask, &b->mask) && |
| 214 | nf_ct_zone(a->master) == nf_ct_zone(b->master); | ||
| 208 | } | 215 | } |
| 209 | 216 | ||
| 210 | /* Generally a bad idea to call this: could have matched already. */ | 217 | /* Generally a bad idea to call this: could have matched already. */ |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 66369490230e..a1c8dd917e12 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <net/netfilter/nf_conntrack_expect.h> | 29 | #include <net/netfilter/nf_conntrack_expect.h> |
| 30 | #include <net/netfilter/nf_conntrack_ecache.h> | 30 | #include <net/netfilter/nf_conntrack_ecache.h> |
| 31 | #include <net/netfilter/nf_conntrack_helper.h> | 31 | #include <net/netfilter/nf_conntrack_helper.h> |
| 32 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 32 | #include <linux/netfilter/nf_conntrack_h323.h> | 33 | #include <linux/netfilter/nf_conntrack_h323.h> |
| 33 | 34 | ||
| 34 | /* Parameters */ | 35 | /* Parameters */ |
| @@ -1216,7 +1217,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, | |||
| 1216 | tuple.dst.u.tcp.port = port; | 1217 | tuple.dst.u.tcp.port = port; |
| 1217 | tuple.dst.protonum = IPPROTO_TCP; | 1218 | tuple.dst.protonum = IPPROTO_TCP; |
| 1218 | 1219 | ||
| 1219 | exp = __nf_ct_expect_find(net, &tuple); | 1220 | exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); |
| 1220 | if (exp && exp->master == ct) | 1221 | if (exp && exp->master == ct) |
| 1221 | return exp; | 1222 | return exp; |
| 1222 | return NULL; | 1223 | return NULL; |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index db35edac307b..51089cfe1167 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -811,7 +811,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
| 811 | if (err < 0) | 811 | if (err < 0) |
| 812 | return err; | 812 | return err; |
| 813 | 813 | ||
| 814 | h = nf_conntrack_find_get(net, &tuple); | 814 | h = nf_conntrack_find_get(net, 0, &tuple); |
| 815 | if (!h) | 815 | if (!h) |
| 816 | return -ENOENT; | 816 | return -ENOENT; |
| 817 | 817 | ||
| @@ -872,7 +872,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
| 872 | if (err < 0) | 872 | if (err < 0) |
| 873 | return err; | 873 | return err; |
| 874 | 874 | ||
| 875 | h = nf_conntrack_find_get(net, &tuple); | 875 | h = nf_conntrack_find_get(net, 0, &tuple); |
| 876 | if (!h) | 876 | if (!h) |
| 877 | return -ENOENT; | 877 | return -ENOENT; |
| 878 | 878 | ||
| @@ -1221,7 +1221,7 @@ ctnetlink_create_conntrack(struct net *net, | |||
| 1221 | int err = -EINVAL; | 1221 | int err = -EINVAL; |
| 1222 | struct nf_conntrack_helper *helper; | 1222 | struct nf_conntrack_helper *helper; |
| 1223 | 1223 | ||
| 1224 | ct = nf_conntrack_alloc(net, otuple, rtuple, GFP_ATOMIC); | 1224 | ct = nf_conntrack_alloc(net, 0, otuple, rtuple, GFP_ATOMIC); |
| 1225 | if (IS_ERR(ct)) | 1225 | if (IS_ERR(ct)) |
| 1226 | return ERR_PTR(-ENOMEM); | 1226 | return ERR_PTR(-ENOMEM); |
| 1227 | 1227 | ||
| @@ -1325,7 +1325,7 @@ ctnetlink_create_conntrack(struct net *net, | |||
| 1325 | if (err < 0) | 1325 | if (err < 0) |
| 1326 | goto err2; | 1326 | goto err2; |
| 1327 | 1327 | ||
| 1328 | master_h = nf_conntrack_find_get(net, &master); | 1328 | master_h = nf_conntrack_find_get(net, 0, &master); |
| 1329 | if (master_h == NULL) { | 1329 | if (master_h == NULL) { |
| 1330 | err = -ENOENT; | 1330 | err = -ENOENT; |
| 1331 | goto err2; | 1331 | goto err2; |
| @@ -1374,9 +1374,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
| 1374 | 1374 | ||
| 1375 | spin_lock_bh(&nf_conntrack_lock); | 1375 | spin_lock_bh(&nf_conntrack_lock); |
| 1376 | if (cda[CTA_TUPLE_ORIG]) | 1376 | if (cda[CTA_TUPLE_ORIG]) |
| 1377 | h = __nf_conntrack_find(net, &otuple); | 1377 | h = __nf_conntrack_find(net, 0, &otuple); |
| 1378 | else if (cda[CTA_TUPLE_REPLY]) | 1378 | else if (cda[CTA_TUPLE_REPLY]) |
| 1379 | h = __nf_conntrack_find(net, &rtuple); | 1379 | h = __nf_conntrack_find(net, 0, &rtuple); |
| 1380 | 1380 | ||
| 1381 | if (h == NULL) { | 1381 | if (h == NULL) { |
| 1382 | err = -ENOENT; | 1382 | err = -ENOENT; |
| @@ -1714,7 +1714,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1714 | if (err < 0) | 1714 | if (err < 0) |
| 1715 | return err; | 1715 | return err; |
| 1716 | 1716 | ||
| 1717 | exp = nf_ct_expect_find_get(net, &tuple); | 1717 | exp = nf_ct_expect_find_get(net, 0, &tuple); |
| 1718 | if (!exp) | 1718 | if (!exp) |
| 1719 | return -ENOENT; | 1719 | return -ENOENT; |
| 1720 | 1720 | ||
| @@ -1770,7 +1770,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1770 | return err; | 1770 | return err; |
| 1771 | 1771 | ||
| 1772 | /* bump usage count to 2 */ | 1772 | /* bump usage count to 2 */ |
| 1773 | exp = nf_ct_expect_find_get(net, &tuple); | 1773 | exp = nf_ct_expect_find_get(net, 0, &tuple); |
| 1774 | if (!exp) | 1774 | if (!exp) |
| 1775 | return -ENOENT; | 1775 | return -ENOENT; |
| 1776 | 1776 | ||
| @@ -1855,7 +1855,7 @@ ctnetlink_create_expect(struct net *net, const struct nlattr * const cda[], | |||
| 1855 | return err; | 1855 | return err; |
| 1856 | 1856 | ||
| 1857 | /* Look for master conntrack of this expectation */ | 1857 | /* Look for master conntrack of this expectation */ |
| 1858 | h = nf_conntrack_find_get(net, &master_tuple); | 1858 | h = nf_conntrack_find_get(net, 0, &master_tuple); |
| 1859 | if (!h) | 1859 | if (!h) |
| 1860 | return -ENOENT; | 1860 | return -ENOENT; |
| 1861 | ct = nf_ct_tuplehash_to_ctrack(h); | 1861 | ct = nf_ct_tuplehash_to_ctrack(h); |
| @@ -1912,7 +1912,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1912 | return err; | 1912 | return err; |
| 1913 | 1913 | ||
| 1914 | spin_lock_bh(&nf_conntrack_lock); | 1914 | spin_lock_bh(&nf_conntrack_lock); |
| 1915 | exp = __nf_ct_expect_find(net, &tuple); | 1915 | exp = __nf_ct_expect_find(net, 0, &tuple); |
| 1916 | 1916 | ||
| 1917 | if (!exp) { | 1917 | if (!exp) { |
| 1918 | spin_unlock_bh(&nf_conntrack_lock); | 1918 | spin_unlock_bh(&nf_conntrack_lock); |
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 3807ac7faf4c..088944824e13 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <net/netfilter/nf_conntrack.h> | 28 | #include <net/netfilter/nf_conntrack.h> |
| 29 | #include <net/netfilter/nf_conntrack_core.h> | 29 | #include <net/netfilter/nf_conntrack_core.h> |
| 30 | #include <net/netfilter/nf_conntrack_helper.h> | 30 | #include <net/netfilter/nf_conntrack_helper.h> |
| 31 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 31 | #include <linux/netfilter/nf_conntrack_proto_gre.h> | 32 | #include <linux/netfilter/nf_conntrack_proto_gre.h> |
| 32 | #include <linux/netfilter/nf_conntrack_pptp.h> | 33 | #include <linux/netfilter/nf_conntrack_pptp.h> |
| 33 | 34 | ||
| @@ -123,7 +124,7 @@ static void pptp_expectfn(struct nf_conn *ct, | |||
| 123 | pr_debug("trying to unexpect other dir: "); | 124 | pr_debug("trying to unexpect other dir: "); |
| 124 | nf_ct_dump_tuple(&inv_t); | 125 | nf_ct_dump_tuple(&inv_t); |
| 125 | 126 | ||
| 126 | exp_other = nf_ct_expect_find_get(net, &inv_t); | 127 | exp_other = nf_ct_expect_find_get(net, nf_ct_zone(ct), &inv_t); |
| 127 | if (exp_other) { | 128 | if (exp_other) { |
| 128 | /* delete other expectation. */ | 129 | /* delete other expectation. */ |
| 129 | pr_debug("found\n"); | 130 | pr_debug("found\n"); |
| @@ -136,17 +137,18 @@ static void pptp_expectfn(struct nf_conn *ct, | |||
| 136 | rcu_read_unlock(); | 137 | rcu_read_unlock(); |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | static int destroy_sibling_or_exp(struct net *net, | 140 | static int destroy_sibling_or_exp(struct net *net, struct nf_conn *ct, |
| 140 | const struct nf_conntrack_tuple *t) | 141 | const struct nf_conntrack_tuple *t) |
| 141 | { | 142 | { |
| 142 | const struct nf_conntrack_tuple_hash *h; | 143 | const struct nf_conntrack_tuple_hash *h; |
| 143 | struct nf_conntrack_expect *exp; | 144 | struct nf_conntrack_expect *exp; |
| 144 | struct nf_conn *sibling; | 145 | struct nf_conn *sibling; |
| 146 | u16 zone = nf_ct_zone(ct); | ||
| 145 | 147 | ||
| 146 | pr_debug("trying to timeout ct or exp for tuple "); | 148 | pr_debug("trying to timeout ct or exp for tuple "); |
| 147 | nf_ct_dump_tuple(t); | 149 | nf_ct_dump_tuple(t); |
| 148 | 150 | ||
| 149 | h = nf_conntrack_find_get(net, t); | 151 | h = nf_conntrack_find_get(net, zone, t); |
| 150 | if (h) { | 152 | if (h) { |
| 151 | sibling = nf_ct_tuplehash_to_ctrack(h); | 153 | sibling = nf_ct_tuplehash_to_ctrack(h); |
| 152 | pr_debug("setting timeout of conntrack %p to 0\n", sibling); | 154 | pr_debug("setting timeout of conntrack %p to 0\n", sibling); |
| @@ -157,7 +159,7 @@ static int destroy_sibling_or_exp(struct net *net, | |||
| 157 | nf_ct_put(sibling); | 159 | nf_ct_put(sibling); |
| 158 | return 1; | 160 | return 1; |
| 159 | } else { | 161 | } else { |
| 160 | exp = nf_ct_expect_find_get(net, t); | 162 | exp = nf_ct_expect_find_get(net, zone, t); |
| 161 | if (exp) { | 163 | if (exp) { |
| 162 | pr_debug("unexpect_related of expect %p\n", exp); | 164 | pr_debug("unexpect_related of expect %p\n", exp); |
| 163 | nf_ct_unexpect_related(exp); | 165 | nf_ct_unexpect_related(exp); |
| @@ -182,7 +184,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) | |||
| 182 | t.dst.protonum = IPPROTO_GRE; | 184 | t.dst.protonum = IPPROTO_GRE; |
| 183 | t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id; | 185 | t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id; |
| 184 | t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id; | 186 | t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id; |
| 185 | if (!destroy_sibling_or_exp(net, &t)) | 187 | if (!destroy_sibling_or_exp(net, ct, &t)) |
| 186 | pr_debug("failed to timeout original pns->pac ct/exp\n"); | 188 | pr_debug("failed to timeout original pns->pac ct/exp\n"); |
| 187 | 189 | ||
| 188 | /* try reply (pac->pns) tuple */ | 190 | /* try reply (pac->pns) tuple */ |
| @@ -190,7 +192,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) | |||
| 190 | t.dst.protonum = IPPROTO_GRE; | 192 | t.dst.protonum = IPPROTO_GRE; |
| 191 | t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id; | 193 | t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id; |
| 192 | t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id; | 194 | t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id; |
| 193 | if (!destroy_sibling_or_exp(net, &t)) | 195 | if (!destroy_sibling_or_exp(net, ct, &t)) |
| 194 | pr_debug("failed to timeout reply pac->pns ct/exp\n"); | 196 | pr_debug("failed to timeout reply pac->pns ct/exp\n"); |
| 195 | } | 197 | } |
| 196 | 198 | ||
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index fbe8ff5a420a..8dd75d90efc0 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <net/netfilter/nf_conntrack_core.h> | 23 | #include <net/netfilter/nf_conntrack_core.h> |
| 24 | #include <net/netfilter/nf_conntrack_expect.h> | 24 | #include <net/netfilter/nf_conntrack_expect.h> |
| 25 | #include <net/netfilter/nf_conntrack_helper.h> | 25 | #include <net/netfilter/nf_conntrack_helper.h> |
| 26 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 26 | #include <linux/netfilter/nf_conntrack_sip.h> | 27 | #include <linux/netfilter/nf_conntrack_sip.h> |
| 27 | 28 | ||
| 28 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
| @@ -836,7 +837,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, | |||
| 836 | 837 | ||
| 837 | rcu_read_lock(); | 838 | rcu_read_lock(); |
| 838 | do { | 839 | do { |
| 839 | exp = __nf_ct_expect_find(net, &tuple); | 840 | exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); |
| 840 | 841 | ||
| 841 | if (!exp || exp->master == ct || | 842 | if (!exp || exp->master == ct || |
| 842 | nfct_help(exp->master)->helper != nfct_help(ct)->helper || | 843 | nfct_help(exp->master)->helper != nfct_help(ct)->helper || |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index e310f1561bb2..24a42efe62ef 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <net/netfilter/nf_conntrack_expect.h> | 26 | #include <net/netfilter/nf_conntrack_expect.h> |
| 27 | #include <net/netfilter/nf_conntrack_helper.h> | 27 | #include <net/netfilter/nf_conntrack_helper.h> |
| 28 | #include <net/netfilter/nf_conntrack_acct.h> | 28 | #include <net/netfilter/nf_conntrack_acct.h> |
| 29 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 29 | 30 | ||
| 30 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
| 31 | 32 | ||
| @@ -171,6 +172,11 @@ static int ct_seq_show(struct seq_file *s, void *v) | |||
| 171 | goto release; | 172 | goto release; |
| 172 | #endif | 173 | #endif |
| 173 | 174 | ||
| 175 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 176 | if (seq_printf(s, "zone=%u ", nf_ct_zone(ct))) | ||
| 177 | goto release; | ||
| 178 | #endif | ||
| 179 | |||
| 174 | if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) | 180 | if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) |
| 175 | goto release; | 181 | goto release; |
| 176 | 182 | ||
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 8183a054256f..61c50fa84703 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <net/netfilter/nf_conntrack.h> | 16 | #include <net/netfilter/nf_conntrack.h> |
| 17 | #include <net/netfilter/nf_conntrack_helper.h> | 17 | #include <net/netfilter/nf_conntrack_helper.h> |
| 18 | #include <net/netfilter/nf_conntrack_ecache.h> | 18 | #include <net/netfilter/nf_conntrack_ecache.h> |
| 19 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 19 | 20 | ||
| 20 | static unsigned int xt_ct_target(struct sk_buff *skb, | 21 | static unsigned int xt_ct_target(struct sk_buff *skb, |
| 21 | const struct xt_target_param *par) | 22 | const struct xt_target_param *par) |
| @@ -69,11 +70,16 @@ static bool xt_ct_tg_check(const struct xt_tgchk_param *par) | |||
| 69 | goto out; | 70 | goto out; |
| 70 | } | 71 | } |
| 71 | 72 | ||
| 73 | #ifndef CONFIG_NF_CONNTRACK_ZONES | ||
| 74 | if (info->zone) | ||
| 75 | goto err1; | ||
| 76 | #endif | ||
| 77 | |||
| 72 | if (nf_ct_l3proto_try_module_get(par->family) < 0) | 78 | if (nf_ct_l3proto_try_module_get(par->family) < 0) |
| 73 | goto err1; | 79 | goto err1; |
| 74 | 80 | ||
| 75 | memset(&t, 0, sizeof(t)); | 81 | memset(&t, 0, sizeof(t)); |
| 76 | ct = nf_conntrack_alloc(par->net, &t, &t, GFP_KERNEL); | 82 | ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); |
| 77 | if (IS_ERR(ct)) | 83 | if (IS_ERR(ct)) |
| 78 | goto err2; | 84 | goto err2; |
| 79 | 85 | ||
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 0d9d18ea2b09..26997ce90e48 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <net/netfilter/nf_conntrack.h> | 28 | #include <net/netfilter/nf_conntrack.h> |
| 29 | #include <net/netfilter/nf_conntrack_core.h> | 29 | #include <net/netfilter/nf_conntrack_core.h> |
| 30 | #include <net/netfilter/nf_conntrack_tuple.h> | 30 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 31 | #include <net/netfilter/nf_conntrack_zones.h> | ||
| 31 | 32 | ||
| 32 | /* we will save the tuples of all connections we care about */ | 33 | /* we will save the tuples of all connections we care about */ |
| 33 | struct xt_connlimit_conn { | 34 | struct xt_connlimit_conn { |
| @@ -114,7 +115,8 @@ static int count_them(struct net *net, | |||
| 114 | 115 | ||
| 115 | /* check the saved connections */ | 116 | /* check the saved connections */ |
| 116 | list_for_each_entry_safe(conn, tmp, hash, list) { | 117 | list_for_each_entry_safe(conn, tmp, hash, list) { |
| 117 | found = nf_conntrack_find_get(net, &conn->tuple); | 118 | found = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE, |
| 119 | &conn->tuple); | ||
| 118 | found_ct = NULL; | 120 | found_ct = NULL; |
| 119 | 121 | ||
| 120 | if (found != NULL) | 122 | if (found != NULL) |
