Commit 5d0aa2cc authored by Patrick McHardy's avatar Patrick McHardy

netfilter: nf_conntrack: add support for "conntrack zones"

Normally, each connection needs a unique identity. Conntrack zones allow
to specify a numerical zone using the CT target, connections in different
zones can use the same identity.

Example:

iptables -t raw -A PREROUTING -i veth0 -j CT --zone 1
iptables -t raw -A OUTPUT -o veth1 -j CT --zone 1
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent 8fea97ec
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
struct xt_ct_target_info { struct xt_ct_target_info {
u_int16_t flags; u_int16_t flags;
u_int16_t __unused; u_int16_t zone;
u_int32_t ct_events; u_int32_t ct_events;
u_int32_t exp_events; u_int32_t exp_events;
char helper[16]; char helper[16];
......
...@@ -352,8 +352,11 @@ enum ip_defrag_users { ...@@ -352,8 +352,11 @@ enum ip_defrag_users {
IP_DEFRAG_LOCAL_DELIVER, IP_DEFRAG_LOCAL_DELIVER,
IP_DEFRAG_CALL_RA_CHAIN, IP_DEFRAG_CALL_RA_CHAIN,
IP_DEFRAG_CONNTRACK_IN, IP_DEFRAG_CONNTRACK_IN,
__IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHORT_MAX,
IP_DEFRAG_CONNTRACK_OUT, IP_DEFRAG_CONNTRACK_OUT,
__IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHORT_MAX,
IP_DEFRAG_CONNTRACK_BRIDGE_IN, IP_DEFRAG_CONNTRACK_BRIDGE_IN,
__IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHORT_MAX,
IP_DEFRAG_VS_IN, IP_DEFRAG_VS_IN,
IP_DEFRAG_VS_OUT, IP_DEFRAG_VS_OUT,
IP_DEFRAG_VS_FWD IP_DEFRAG_VS_FWD
......
...@@ -355,8 +355,11 @@ struct inet_frag_queue; ...@@ -355,8 +355,11 @@ struct inet_frag_queue;
enum ip6_defrag_users { enum ip6_defrag_users {
IP6_DEFRAG_LOCAL_DELIVER, IP6_DEFRAG_LOCAL_DELIVER,
IP6_DEFRAG_CONNTRACK_IN, IP6_DEFRAG_CONNTRACK_IN,
__IP6_DEFRAG_CONNTRACK_IN = IP6_DEFRAG_CONNTRACK_IN + USHORT_MAX,
IP6_DEFRAG_CONNTRACK_OUT, IP6_DEFRAG_CONNTRACK_OUT,
__IP6_DEFRAG_CONNTRACK_OUT = IP6_DEFRAG_CONNTRACK_OUT + USHORT_MAX,
IP6_DEFRAG_CONNTRACK_BRIDGE_IN, IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
__IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHORT_MAX,
}; };
struct ip6_create_arg { struct ip6_create_arg {
......
...@@ -198,7 +198,8 @@ extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int null ...@@ -198,7 +198,8 @@ extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int null
extern void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size); extern void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size);
extern struct nf_conntrack_tuple_hash * extern struct nf_conntrack_tuple_hash *
__nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple); __nf_conntrack_find(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple);
extern void nf_conntrack_hash_insert(struct nf_conn *ct); extern void nf_conntrack_hash_insert(struct nf_conn *ct);
extern void nf_ct_delete_from_lists(struct nf_conn *ct); extern void nf_ct_delete_from_lists(struct nf_conn *ct);
...@@ -267,7 +268,7 @@ extern void ...@@ -267,7 +268,7 @@ extern void
nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data); nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data);
extern void nf_conntrack_free(struct nf_conn *ct); extern void nf_conntrack_free(struct nf_conn *ct);
extern struct nf_conn * extern struct nf_conn *
nf_conntrack_alloc(struct net *net, nf_conntrack_alloc(struct net *net, u16 zone,
const struct nf_conntrack_tuple *orig, const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_tuple *repl, const struct nf_conntrack_tuple *repl,
gfp_t gfp); gfp_t gfp);
......
...@@ -49,7 +49,8 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, ...@@ -49,7 +49,8 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
/* Find a connection corresponding to a tuple. */ /* Find a connection corresponding to a tuple. */
extern struct nf_conntrack_tuple_hash * extern struct nf_conntrack_tuple_hash *
nf_conntrack_find_get(struct net *net, const struct nf_conntrack_tuple *tuple); nf_conntrack_find_get(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple);
extern int __nf_conntrack_confirm(struct sk_buff *skb); extern int __nf_conntrack_confirm(struct sk_buff *skb);
......
...@@ -74,13 +74,16 @@ int nf_conntrack_expect_init(struct net *net); ...@@ -74,13 +74,16 @@ int nf_conntrack_expect_init(struct net *net);
void nf_conntrack_expect_fini(struct net *net); void nf_conntrack_expect_fini(struct net *net);
struct nf_conntrack_expect * struct nf_conntrack_expect *
__nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple); __nf_ct_expect_find(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple);
struct nf_conntrack_expect * struct nf_conntrack_expect *
nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple); nf_ct_expect_find_get(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple);
struct nf_conntrack_expect * struct nf_conntrack_expect *
nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple); nf_ct_find_expectation(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple);
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp); void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
void nf_ct_remove_expectations(struct nf_conn *ct); void nf_ct_remove_expectations(struct nf_conn *ct);
......
...@@ -8,6 +8,7 @@ enum nf_ct_ext_id { ...@@ -8,6 +8,7 @@ enum nf_ct_ext_id {
NF_CT_EXT_NAT, NF_CT_EXT_NAT,
NF_CT_EXT_ACCT, NF_CT_EXT_ACCT,
NF_CT_EXT_ECACHE, NF_CT_EXT_ECACHE,
NF_CT_EXT_ZONE,
NF_CT_EXT_NUM, NF_CT_EXT_NUM,
}; };
...@@ -15,6 +16,7 @@ enum nf_ct_ext_id { ...@@ -15,6 +16,7 @@ enum nf_ct_ext_id {
#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
#define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache
#define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone
/* Extensions: optional stuff which isn't permanently in struct. */ /* Extensions: optional stuff which isn't permanently in struct. */
struct nf_ct_ext { struct nf_ct_ext {
......
#ifndef _NF_CONNTRACK_ZONES_H
#define _NF_CONNTRACK_ZONES_H
#include <net/netfilter/nf_conntrack_extend.h>
#define NF_CT_DEFAULT_ZONE 0
struct nf_conntrack_zone {
u16 id;
};
static inline u16 nf_ct_zone(const struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_ZONES
struct nf_conntrack_zone *nf_ct_zone;
nf_ct_zone = nf_ct_ext_find(ct, NF_CT_EXT_ZONE);
if (nf_ct_zone)
return nf_ct_zone->id;
#endif
return NF_CT_DEFAULT_ZONE;
}
#endif /* _NF_CONNTRACK_ZONES_H */
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/nf_nat_helper.h> #include <net/netfilter/nf_nat_helper.h>
...@@ -266,7 +267,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) ...@@ -266,7 +267,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
return -EINVAL; return -EINVAL;
} }
h = nf_conntrack_find_get(sock_net(sk), &tuple); h = nf_conntrack_find_get(sock_net(sk), NF_CT_DEFAULT_ZONE, &tuple);
if (h) { if (h) {
struct sockaddr_in sin; struct sockaddr_in sin;
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/nf_log.h> #include <net/netfilter/nf_log.h>
static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ; 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,13 +115,14 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
/* Returns conntrack if it dealt with ICMP, and filled in skb fields */ /* Returns conntrack if it dealt with ICMP, and filled in skb fields */
static int static int
icmp_error_message(struct net *net, struct sk_buff *skb, icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
enum ip_conntrack_info *ctinfo, enum ip_conntrack_info *ctinfo,
unsigned int hooknum) unsigned int hooknum)
{ {
struct nf_conntrack_tuple innertuple, origtuple; struct nf_conntrack_tuple innertuple, origtuple;
const struct nf_conntrack_l4proto *innerproto; const struct nf_conntrack_l4proto *innerproto;
const struct nf_conntrack_tuple_hash *h; const struct nf_conntrack_tuple_hash *h;
u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE;
NF_CT_ASSERT(skb->nfct == NULL); NF_CT_ASSERT(skb->nfct == NULL);
...@@ -146,7 +148,7 @@ icmp_error_message(struct net *net, struct sk_buff *skb, ...@@ -146,7 +148,7 @@ icmp_error_message(struct net *net, struct sk_buff *skb,
*ctinfo = IP_CT_RELATED; *ctinfo = IP_CT_RELATED;
h = nf_conntrack_find_get(net, &innertuple); h = nf_conntrack_find_get(net, zone, &innertuple);
if (!h) { if (!h) {
pr_debug("icmp_error_message: no match\n"); pr_debug("icmp_error_message: no match\n");
return -NF_ACCEPT; return -NF_ACCEPT;
...@@ -209,7 +211,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, ...@@ -209,7 +211,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl,
icmph->type != ICMP_REDIRECT) icmph->type != ICMP_REDIRECT)
return NF_ACCEPT; return NF_ACCEPT;
return icmp_error_message(net, skb, ctinfo, hooknum); return icmp_error_message(net, tmpl, skb, ctinfo, hooknum);
} }
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/netfilter_bridge.h> #include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv4/nf_defrag_ipv4.h> #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
...@@ -39,15 +40,20 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) ...@@ -39,15 +40,20 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
struct sk_buff *skb) struct sk_buff *skb)
{ {
u16 zone = NF_CT_DEFAULT_ZONE;
if (skb->nfct)
zone = nf_ct_zone((struct nf_conn *)skb->nfct);
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
if (skb->nf_bridge && if (skb->nf_bridge &&
skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
return IP_DEFRAG_CONNTRACK_BRIDGE_IN; return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
#endif #endif
if (hooknum == NF_INET_PRE_ROUTING) if (hooknum == NF_INET_PRE_ROUTING)
return IP_DEFRAG_CONNTRACK_IN; return IP_DEFRAG_CONNTRACK_IN + zone;
else else
return IP_DEFRAG_CONNTRACK_OUT; return IP_DEFRAG_CONNTRACK_OUT + zone;
} }
static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_zones.h>
static DEFINE_SPINLOCK(nf_nat_lock); static DEFINE_SPINLOCK(nf_nat_lock);
...@@ -69,13 +70,14 @@ EXPORT_SYMBOL_GPL(nf_nat_proto_put); ...@@ -69,13 +70,14 @@ EXPORT_SYMBOL_GPL(nf_nat_proto_put);
/* We keep an extra hash for each conntrack, for fast searching. */ /* We keep an extra hash for each conntrack, for fast searching. */
static inline unsigned int static inline unsigned int
hash_by_src(const struct net *net, const struct nf_conntrack_tuple *tuple) hash_by_src(const struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple)
{ {
unsigned int hash; unsigned int hash;
/* Original src, to ensure we map it consistently if poss. */ /* Original src, to ensure we map it consistently if poss. */
hash = jhash_3words((__force u32)tuple->src.u3.ip, hash = jhash_3words((__force u32)tuple->src.u3.ip,
(__force u32)tuple->src.u.all, (__force u32)tuple->src.u.all ^ zone,
tuple->dst.protonum, 0); tuple->dst.protonum, 0);
return ((u64)hash * net->ipv4.nat_htable_size) >> 32; return ((u64)hash * net->ipv4.nat_htable_size) >> 32;
} }
...@@ -139,12 +141,12 @@ same_src(const struct nf_conn *ct, ...@@ -139,12 +141,12 @@ same_src(const struct nf_conn *ct,
/* Only called for SRC manip */ /* Only called for SRC manip */
static int static int
find_appropriate_src(struct net *net, find_appropriate_src(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *tuple,
struct nf_conntrack_tuple *result, struct nf_conntrack_tuple *result,
const struct nf_nat_range *range) const struct nf_nat_range *range)
{ {
unsigned int h = hash_by_src(net, tuple); unsigned int h = hash_by_src(net, zone, tuple);
const struct nf_conn_nat *nat; const struct nf_conn_nat *nat;
const struct nf_conn *ct; const struct nf_conn *ct;
const struct hlist_node *n; const struct hlist_node *n;
...@@ -152,7 +154,7 @@ find_appropriate_src(struct net *net, ...@@ -152,7 +154,7 @@ find_appropriate_src(struct net *net,
rcu_read_lock(); rcu_read_lock();
hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) { hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) {
ct = nat->ct; ct = nat->ct;
if (same_src(ct, tuple)) { if (same_src(ct, tuple) && nf_ct_zone(ct) == zone) {
/* Copy source part from reply tuple. */ /* Copy source part from reply tuple. */
nf_ct_invert_tuplepr(result, nf_ct_invert_tuplepr(result,
&ct->tuplehash[IP_CT_DIR_REPLY].tuple); &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
...@@ -175,7 +177,7 @@ find_appropriate_src(struct net *net, ...@@ -175,7 +177,7 @@ find_appropriate_src(struct net *net,
the ip with the lowest src-ip/dst-ip/proto usage. the ip with the lowest src-ip/dst-ip/proto usage.
*/ */
static void static void
find_best_ips_proto(struct nf_conntrack_tuple *tuple, find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
const struct nf_nat_range *range, const struct nf_nat_range *range,
const struct nf_conn *ct, const struct nf_conn *ct,
enum nf_nat_manip_type maniptype) enum nf_nat_manip_type maniptype)
...@@ -209,7 +211,7 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple, ...@@ -209,7 +211,7 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple,
maxip = ntohl(range->max_ip); maxip = ntohl(range->max_ip);
j = jhash_2words((__force u32)tuple->src.u3.ip, j = jhash_2words((__force u32)tuple->src.u3.ip,
range->flags & IP_NAT_RANGE_PERSISTENT ? range->flags & IP_NAT_RANGE_PERSISTENT ?
0 : (__force u32)tuple->dst.u3.ip, 0); 0 : (__force u32)tuple->dst.u3.ip ^ zone, 0);
j = ((u64)j * (maxip - minip + 1)) >> 32; j = ((u64)j * (maxip - minip + 1)) >> 32;
*var_ipp = htonl(minip + j); *var_ipp = htonl(minip + j);
} }
...@@ -229,6 +231,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, ...@@ -229,6 +231,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
const struct nf_nat_protocol *proto; const struct nf_nat_protocol *proto;
u16 zone = nf_ct_zone(ct);
/* 1) If this srcip/proto/src-proto-part is currently mapped, /* 1) If this srcip/proto/src-proto-part is currently mapped,
and that same mapping gives a unique tuple within the given and that same mapping gives a unique tuple within the given
...@@ -239,7 +242,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, ...@@ -239,7 +242,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
manips not an issue. */ manips not an issue. */
if (maniptype == IP_NAT_MANIP_SRC && if (maniptype == IP_NAT_MANIP_SRC &&
!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
if (find_appropriate_src(net, orig_tuple, tuple, range)) { if (find_appropriate_src(net, zone, orig_tuple, tuple, range)) {
pr_debug("get_unique_tuple: Found current src map\n"); pr_debug("get_unique_tuple: Found current src map\n");
if (!nf_nat_used_tuple(tuple, ct)) if (!nf_nat_used_tuple(tuple, ct))
return; return;
...@@ -249,7 +252,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, ...@@ -249,7 +252,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
/* 2) Select the least-used IP/proto combination in the given /* 2) Select the least-used IP/proto combination in the given
range. */ range. */
*tuple = *orig_tuple; *tuple = *orig_tuple;
find_best_ips_proto(tuple, range, ct, maniptype); find_best_ips_proto(zone, tuple, range, ct, maniptype);
/* 3) The per-protocol part of the manip is made to map into /* 3) The per-protocol part of the manip is made to map into
the range to make a unique tuple. */ the range to make a unique tuple. */
...@@ -327,7 +330,8 @@ nf_nat_setup_info(struct nf_conn *ct, ...@@ -327,7 +330,8 @@ nf_nat_setup_info(struct nf_conn *ct,
if (have_to_hash) { if (have_to_hash) {
unsigned int srchash; unsigned int srchash;
srchash = hash_by_src(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); srchash = hash_by_src(net, nf_ct_zone(ct),
&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
spin_lock_bh(&nf_nat_lock); spin_lock_bh(&nf_nat_lock);
/* nf_conntrack_alter_reply might re-allocate exntension aera */ /* nf_conntrack_alter_reply might re-allocate exntension aera */
nat = nfct_nat(ct); nat = nfct_nat(ct);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <net/netfilter/nf_nat_rule.h> #include <net/netfilter/nf_nat_rule.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <linux/netfilter/nf_conntrack_proto_gre.h> #include <linux/netfilter/nf_conntrack_proto_gre.h>
#include <linux/netfilter/nf_conntrack_pptp.h> #include <linux/netfilter/nf_conntrack_pptp.h>
...@@ -74,7 +75,7 @@ static void pptp_nat_expected(struct nf_conn *ct, ...@@ -74,7 +75,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
pr_debug("trying to unexpect other dir: "); pr_debug("trying to unexpect other dir: ");
nf_ct_dump_tuple_ip(&t); nf_ct_dump_tuple_ip(&t);
other_exp = nf_ct_expect_find_get(net, &t); other_exp = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t);
if (other_exp) { if (other_exp) {
nf_ct_unexpect_related(other_exp); nf_ct_unexpect_related(other_exp);
nf_ct_expect_put(other_exp); nf_ct_expect_put(other_exp);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
#include <net/netfilter/nf_log.h> #include <net/netfilter/nf_log.h>
...@@ -191,15 +192,20 @@ static unsigned int ipv6_confirm(unsigned int hooknum, ...@@ -191,15 +192,20 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
struct sk_buff *skb) struct sk_buff *skb)
{ {
u16 zone = NF_CT_DEFAULT_ZONE;
if (skb->nfct)
zone = nf_ct_zone((struct nf_conn *)skb->nfct);
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
if (skb->nf_bridge && if (skb->nf_bridge &&
skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
return IP6_DEFRAG_CONNTRACK_BRIDGE_IN; return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
#endif #endif
if (hooknum == NF_INET_PRE_ROUTING) if (hooknum == NF_INET_PRE_ROUTING)
return IP6_DEFRAG_CONNTRACK_IN; return IP6_DEFRAG_CONNTRACK_IN + zone;
else else
return IP6_DEFRAG_CONNTRACK_OUT; return IP6_DEFRAG_CONNTRACK_OUT + zone;
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
#include <net/netfilter/nf_log.h> #include <net/netfilter/nf_log.h>
...@@ -128,7 +129,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, ...@@ -128,7 +129,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb,
} }
static int static int
icmpv6_error_message(struct net *net, icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int icmp6off, unsigned int icmp6off,
enum ip_conntrack_info *ctinfo, enum ip_conntrack_info *ctinfo,
...@@ -137,6 +138,7 @@ icmpv6_error_message(struct net *net, ...@@ -137,6 +138,7 @@ icmpv6_error_message(struct net *net,
struct nf_conntrack_tuple intuple, origtuple; struct nf_conntrack_tuple intuple, origtuple;
const struct nf_conntrack_tuple_hash *h; const struct nf_conntrack_tuple_hash *h;
const struct nf_conntrack_l4proto *inproto; const struct nf_conntrack_l4proto *inproto;
u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE;
NF_CT_ASSERT(skb->nfct == NULL); NF_CT_ASSERT(skb->nfct == NULL);
...@@ -163,7 +165,7 @@ icmpv6_error_message(struct net *net, ...@@ -163,7 +165,7 @@ icmpv6_error_message(struct net *net,
*ctinfo = IP_CT_RELATED; *ctinfo = IP_CT_RELATED;
h = nf_conntrack_find_get(net, &intuple); h = nf_conntrack_find_get(net, zone, &intuple);
if (!h) { if (!h) {
pr_debug("icmpv6_error: no match\n"); pr_debug("icmpv6_error: no match\n");
return -NF_ACCEPT; return -NF_ACCEPT;
...@@ -216,7 +218,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, ...@@ -216,7 +218,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl,
if (icmp6h->icmp6_type >= 128) if (icmp6h->icmp6_type >= 128)
return NF_ACCEPT; return NF_ACCEPT;
return icmpv6_error_message(net, skb, dataoff, ctinfo, hooknum); return icmpv6_error_message(net, tmpl, skb, dataoff, ctinfo, hooknum);
} }
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
......
...@@ -83,6 +83,19 @@ config NF_CONNTRACK_SECMARK ...@@ -83,6 +83,19 @@ config NF_CONNTRACK_SECMARK
If unsure, say 'N'. If unsure, say 'N'.
config NF_CONNTRACK_ZONES
bool 'Connection tracking zones'
depends on NETFILTER_ADVANCED
depends on NETFILTER_XT_TARGET_CT
help
This option enables support for connection tracking zones.
Normally, each connection needs to have a unique system wide
identity. Connection tracking zones allow to have multiple
connections using the same identity, as long as they are
contained in different zones.
If unsure, say `N'.
config NF_CONNTRACK_EVENTS config NF_CONNTRACK_EVENTS
bool "Connection tracking events" bool "Connection tracking events"
depends on NETFILTER_ADVANCED depends on NETFILTER_ADVANCED
......
This diff is collapsed.
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_zones.h>
unsigned int nf_ct_expect_hsize __read_mostly; unsigned int nf_ct_expect_hsize __read_mostly;
EXPORT_SYMBOL_GPL(nf_ct_expect_hsize); 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,7 +85,8 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple
} }
struct nf_conntrack_expect * struct nf_conntrack_expect *
__nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple) __nf_ct_expect_find(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple)
{ {
struct nf_conntrack_expect *i; struct nf_conntrack_expect *i;
struct hlist_node *n; struct hlist_node *n;
...@@ -95,7 +97,8 @@ __nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple) ...@@ -95,7 +97,8 @@ __nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple)
h = nf_ct_expect_dst_hash(tuple); h = nf_ct_expect_dst_hash(tuple);
hlist_for_each_entry_rcu(i, n, &net->ct.expect_hash[h], hnode) { hlist_for_each_entry_rcu(i, n, &net->ct.expect_hash[h], hnode) {
if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) &&
nf_ct_zone(i->master) == zone)
return i; return i;
} }
return NULL; return NULL;
...@@ -104,12 +107,13 @@ EXPORT_SYMBOL_GPL(__nf_ct_expect_find); ...@@ -104,12 +107,13 @@ EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
/* Just find a expectation corresponding to a tuple. */ /* Just find a expectation corresponding to a tuple. */
struct nf_conntrack_expect * struct nf_conntrack_expect *
nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple) nf_ct_expect_find_get(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple)
{ {
struct nf_conntrack_expect *i; struct nf_conntrack_expect *i;
rcu_read_lock(); rcu_read_lock();
i = __nf_ct_expect_find(net, tuple); i = __nf_ct_expect_find(net, zone, tuple);
if (i && !atomic_inc_not_zero(&i->use)) if (i && !atomic_inc_not_zero(&i->use))
i = NULL; i = NULL;
rcu_read_unlock(); rcu_read_unlock();
...@@ -121,7 +125,8 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get); ...@@ -121,7 +125,8 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
/* If an expectation for this connection is found, it gets delete from /* If an expectation for this connection is found, it gets delete from
* global list then returned. */ * global list then returned. */
struct nf_conntrack_expect * struct nf_conntrack_expect *
nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple) nf_ct_find_expectation(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple)
{ {
struct nf_conntrack_expect *i, *exp = NULL; struct nf_conntrack_expect *i, *exp = NULL;
struct hlist_node *n; struct hlist_node *n;
...@@ -133,7 +138,8 @@ nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple) ...@@ -133,7 +138,8 @@ nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple)
h = nf_ct_expect_dst_hash(tuple); h = nf_ct_expect_dst_hash(tuple);
hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
if (!(i->flags & NF_CT_EXPECT_INACTIVE) && if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) { nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) &&
nf_ct_zone(i->master) == zone) {
exp = i; exp = i;
break; break;
} }
...@@ -204,7 +210,8 @@ static inline int expect_matches(const struct nf_conntrack_expect *a, ...@@ -204,7 +210,8 @@ static inline int expect_matches(const struct nf_conntrack_expect *a,
{ {
return a->master == b->master && a->class == b->class && return a->master == b->master && a->class == b->class &&
nf_ct_tuple_equal(&a->tuple, &b->tuple) && nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
nf_ct_tuple_mask_equal(&a->mask, &b->mask); nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
nf_ct_zone(a->master) == nf_ct_zone(b->master);
} }
/* Generally a bad idea to call this: could have matched already. */ /* Generally a bad idea to call this: could have matched already. */
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <linux/netfilter/nf_conntrack_h323.h> #include <linux/netfilter/nf_conntrack_h323.h>
/* Parameters */ /* Parameters */
...@@ -1216,7 +1217,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, ...@@ -1216,7 +1217,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
tuple.dst.u.tcp.port = port; tuple.dst.u.tcp.port = port;
tuple.dst.protonum = IPPROTO_TCP; tuple.dst.protonum = IPPROTO_TCP;
exp = __nf_ct_expect_find(net, &tuple); exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
if (exp && exp->master == ct) if (exp && exp->master == ct)
return exp; return exp;
return NULL; return NULL;
......
...@@ -811,7 +811,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -811,7 +811,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (err < 0) if (err < 0)
return err; return err;
h = nf_conntrack_find_get(net, &tuple); h = nf_conntrack_find_get(net, 0, &tuple);
if (!h) if (!h)
return -ENOENT; return -ENOENT;
...@@ -872,7 +872,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -872,7 +872,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (err < 0) if (err < 0)
return err; return err;
h = nf_conntrack_find_get(net, &tuple); h = nf_conntrack_find_get(net, 0, &tuple);
if (!h) if (!h)
return -ENOENT; return -ENOENT;
...@@ -1221,7 +1221,7 @@ ctnetlink_create_conntrack(struct net *net, ...@@ -1221,7 +1221,7 @@ ctnetlink_create_conntrack(struct net *net,
int err = -EINVAL; int err = -EINVAL;
struct nf_conntrack_helper *helper; struct nf_conntrack_helper *helper;
ct = nf_conntrack_alloc(net, otuple, rtuple, GFP_ATOMIC); ct = nf_conntrack_alloc(net, 0, otuple, rtuple, GFP_ATOMIC);
if (IS_ERR(ct)) if (IS_ERR(ct))
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -1325,7 +1325,7 @@ ctnetlink_create_conntrack(struct net *net, ...@@ -1325,7 +1325,7 @@ ctnetlink_create_conntrack(struct net *net,
if (err < 0) if (err < 0)
goto err2; goto err2;
master_h = nf_conntrack_find_get(net, &master); master_h = nf_conntrack_find_get(net, 0, &master);
if (master_h == NULL) { if (master_h == NULL) {
err = -ENOENT; err = -ENOENT;
goto err2; goto err2;
...@@ -1374,9 +1374,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -1374,9 +1374,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
spin_lock_bh(&nf_conntrack_lock); spin_lock_bh(&nf_conntrack_lock);
if (cda[CTA_TUPLE_ORIG]) if (cda[CTA_TUPLE_ORIG])
h = __nf_conntrack_find(net, &otuple); h = __nf_conntrack_find(net, 0, &otuple);
else if (cda[CTA_TUPLE_REPLY]) else if (cda[CTA_TUPLE_REPLY])
h = __nf_conntrack_find(net, &rtuple); h = __nf_conntrack_find(net, 0, &rtuple);
if (h == NULL) { if (h == NULL) {
err = -ENOENT; err = -ENOENT;
...@@ -1714,7 +1714,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, ...@@ -1714,7 +1714,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (err < 0) if (err < 0)
return err; return err;
exp = nf_ct_expect_find_get(net, &tuple); exp = nf_ct_expect_find_get(net, 0, &tuple);
if (!exp) if (!exp)
return -ENOENT; return -ENOENT;
...@@ -1770,7 +1770,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, ...@@ -1770,7 +1770,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
return err; return err;
/* bump usage count to 2 */ /* bump usage count to 2 */
exp = nf_ct_expect_find_get(net, &tuple); exp = nf_ct_expect_find_get(net, 0, &tuple);
if (!exp) if (!exp)
return -ENOENT; return -ENOENT;
...@@ -1855,7 +1855,7 @@ ctnetlink_create_expect(struct net *net, const struct nlattr * const cda[], ...@@ -1855,7 +1855,7 @@ ctnetlink_create_expect(struct net *net, const struct nlattr * const cda[],
return err; return err;
/* Look for master conntrack of this expectation */ /* Look for master conntrack of this expectation */
h = nf_conntrack_find_get(net, &master_tuple); h = nf_conntrack_find_get(net, 0, &master_tuple);
if (!h) if (!h)
return -ENOENT; return -ENOENT;
ct = nf_ct_tuplehash_to_ctrack(h); ct = nf_ct_tuplehash_to_ctrack(h);
...@@ -1912,7 +1912,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, ...@@ -1912,7 +1912,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
return err; return err;
spin_lock_bh(&nf_conntrack_lock); spin_lock_bh(&nf_conntrack_lock);
exp = __nf_ct_expect_find(net, &tuple); exp = __nf_ct_expect_find(net, 0, &tuple);
if (!exp) { if (!exp) {
spin_unlock_bh(&nf_conntrack_lock); spin_unlock_bh(&nf_conntrack_lock);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <linux/netfilter/nf_conntrack_proto_gre.h> #include <linux/netfilter/nf_conntrack_proto_gre.h>
#include <linux/netfilter/nf_conntrack_pptp.h> #include <linux/netfilter/nf_conntrack_pptp.h>
...@@ -123,7 +124,7 @@ static void pptp_expectfn(struct nf_conn *ct, ...@@ -123,7 +124,7 @@ static void pptp_expectfn(struct nf_conn *ct,
pr_debug("trying to unexpect other dir: "); pr_debug("trying to unexpect other dir: ");
nf_ct_dump_tuple(&inv_t); nf_ct_dump_tuple(&inv_t);
exp_other = nf_ct_expect_find_get(net, &inv_t); exp_other = nf_ct_expect_find_get(net, nf_ct_zone(ct), &inv_t);
if (exp_other) { if (exp_other) {
/* delete other expectation. */ /* delete other expectation. */
pr_debug("found\n"); pr_debug("found\n");
...@@ -136,17 +137,18 @@ static void pptp_expectfn(struct nf_conn *ct, ...@@ -136,17 +137,18 @@ static void pptp_expectfn(struct nf_conn *ct,
rcu_read_unlock(); rcu_read_unlock();
} }
static int destroy_sibling_or_exp(struct net *net, static int destroy_sibling_or_exp(struct net *net, struct nf_conn *ct,
const struct nf_conntrack_tuple *t) const struct nf_conntrack_tuple *t)
{ {
const struct nf_conntrack_tuple_hash *h; const struct nf_conntrack_tuple_hash *h;
struct nf_conntrack_expect *exp; struct nf_conntrack_expect *exp;
struct nf_conn *sibling; struct nf_conn *sibling;
u16 zone = nf_ct_zone(ct);
pr_debug("trying to timeout ct or exp for tuple "); pr_debug("trying to timeout ct or exp for tuple ");
nf_ct_dump_tuple(t); nf_ct_dump_tuple(t);
h = nf_conntrack_find_get(net, t); h = nf_conntrack_find_get(net, zone, t);
if (h) { if (h) {
sibling = nf_ct_tuplehash_to_ctrack(h); sibling = nf_ct_tuplehash_to_ctrack(h);
pr_debug("setting timeout of conntrack %p to 0\n", sibling); 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,7 +159,7 @@ static int destroy_sibling_or_exp(struct net *net,
nf_ct_put(sibling); nf_ct_put(sibling);
return 1; return 1;
} else { } else {
exp = nf_ct_expect_find_get(net, t); exp = nf_ct_expect_find_get(net, zone, t);
if (exp) { if (exp) {
pr_debug("unexpect_related of expect %p\n", exp); pr_debug("unexpect_related of expect %p\n", exp);
nf_ct_unexpect_related(exp); nf_ct_unexpect_related(exp);
...@@ -182,7 +184,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) ...@@ -182,7 +184,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
t.dst.protonum = IPPROTO_GRE; t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id; t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id;
t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id; t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id;
if (!destroy_sibling_or_exp(net, &t)) if (!destroy_sibling_or_exp(net, ct, &t))
pr_debug("failed to timeout original pns->pac ct/exp\n"); pr_debug("failed to timeout original pns->pac ct/exp\n");
/* try reply (pac->pns) tuple */ /* try reply (pac->pns) tuple */
...@@ -190,7 +192,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) ...@@ -190,7 +192,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
t.dst.protonum = IPPROTO_GRE; t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id; t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id;
t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id; t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id;
if (!destroy_sibling_or_exp(net, &t)) if (!destroy_sibling_or_exp(net, ct, &t))
pr_debug("failed to timeout reply pac->pns ct/exp\n"); pr_debug("failed to timeout reply pac->pns ct/exp\n");
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <linux/netfilter/nf_conntrack_sip.h> #include <linux/netfilter/nf_conntrack_sip.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -836,7 +837,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, ...@@ -836,7 +837,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff,
rcu_read_lock(); rcu_read_lock();
do { do {
exp = __nf_ct_expect_find(net, &tuple); exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
if (!exp || exp->master == ct || if (!exp || exp->master == ct ||
nfct_help(exp->master)->helper != nfct_help(ct)->helper || nfct_help(exp->master)->helper != nfct_help(ct)->helper ||
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_acct.h> #include <net/netfilter/nf_conntrack_acct.h>
#include <net/netfilter/nf_conntrack_zones.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -171,6 +172,11 @@ static int ct_seq_show(struct seq_file *s, void *v) ...@@ -171,6 +172,11 @@ static int ct_seq_show(struct seq_file *s, void *v)
goto release; goto release;
#endif #endif
#ifdef CONFIG_NF_CONNTRACK_ZONES
if (seq_printf(s, "zone=%u ", nf_ct_zone(ct)))
goto release;
#endif
if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
goto release; goto release;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_zones.h>
static unsigned int xt_ct_target(struct sk_buff *skb, static unsigned int xt_ct_target(struct sk_buff *skb,
const struct xt_target_param *par) const struct xt_target_param *par)
...@@ -69,11 +70,16 @@ static bool xt_ct_tg_check(const struct xt_tgchk_param *par) ...@@ -69,11 +70,16 @@ static bool xt_ct_tg_check(const struct xt_tgchk_param *par)
goto out; goto out;
} }
#ifndef CONFIG_NF_CONNTRACK_ZONES
if (info->zone)
goto err1;
#endif
if (nf_ct_l3proto_try_module_get(par->family) < 0) if (nf_ct_l3proto_try_module_get(par->family) < 0)
goto err1; goto err1;
memset(&t, 0, sizeof(t)); memset(&t, 0, sizeof(t));
ct = nf_conntrack_alloc(par->net, &t, &t, GFP_KERNEL); ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
if (IS_ERR(ct)) if (IS_ERR(ct))
goto err2; goto err2;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_zones.h>
/* we will save the tuples of all connections we care about */ /* we will save the tuples of all connections we care about */
struct xt_connlimit_conn { struct xt_connlimit_conn {
...@@ -114,7 +115,8 @@ static int count_them(struct net *net, ...@@ -114,7 +115,8 @@ static int count_them(struct net *net,
/* check the saved connections */ /* check the saved connections */
list_for_each_entry_safe(conn, tmp, hash, list) { list_for_each_entry_safe(conn, tmp, hash, list) {
found = nf_conntrack_find_get(net, &conn->tuple); found = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE,
&conn->tuple);
found_ct = NULL; found_ct = NULL;
if (found != NULL) if (found != NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment