Skip to contentSkip to conversation

: netfilter: CT target/conntrack zones

PATCH In review Patrick McHardy 4 participants 24 messages Jan 25, 2010 – Jan 26, 2010

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover : netfilter: CT target/conntrack zones

The following patches contain a new version of the conntrack zones patchset, including a new xtables target to (among other things) assign conntracks to a specific zone, replacing the device attribute used in the previous version.

Quick overview:

- Patch 1 adds a struct net * parameter to the xtables target parameter structures as preparation for the CT target, which needs to allocate a conntrack entry in the proper namespace

- Patch 2 splits up the IPCT_STATUS event as requested by Jozsef. The CT target can be used for selective conntrack event delivery, this allows more fine grained control over the delivered events.

- Patch 3 adds selective conntrack event delivery by adding two masks for conntrack and expectation events to struct nf_conntrack_ecache, which are used to filter out events.

- Patch 4 fixes ctnetlink to only assign helpers for matching protocols to conntrack entries and fixes expectation deletion by helper name. This is also preparation for the CT target, which can also assign helpers to new connections.

- Patch 5 adds support for conntrack templates, which are specially marked conntrack entries attached to the skb that are used to initialize specific parameters of new connections.

- Patch 6 adds the CT target

- Patch 7 contains preparatory work for assigning conntracks to zones:
the template needs to be passed to L4 ->error handlers for ICMP and ICMPv6 to perform the conntrack lookup in the correct zone

- Patch 8 adds zone support to nf_conntrack and the CT target. This works by incorporating a numerical "zone" identifier into the conntrack/NAT hashes and comparing it during lookups.

- Patch 9 adds zone support to ctnetlink by dumping and parsing a new CTA_ZONE attribute that contains the zone ID.

Comments welcome.

 include/linux/netfilter/nf_conntrack_common.h  |   22 +++
 include/linux/netfilter/nfnetlink_conntrack.h  |    2 +
 include/linux/netfilter/x_tables.h             |    2 +
 include/linux/netfilter/xt_CT.h                |   14 ++
 include/net/ip.h                               |    3 +
 include/net/ipv6.h                             |    3 +
 include/net/netfilter/nf_conntrack.h           |    5 +-
 include/net/netfilter/nf_conntrack_core.h      |    3 +-
 include/net/netfilter/nf_conntrack_ecache.h    |   58 ++++-----
 include/net/netfilter/nf_conntrack_expect.h    |    9 +-
 include/net/netfilter/nf_conntrack_extend.h    |    2 +
 include/net/netfilter/nf_conntrack_helper.h    |    8 +-
 include/net/netfilter/nf_conntrack_l4proto.h   |    4 +-
 include/net/netfilter/nf_conntrack_zones.h     |   21 +++
 net/bridge/netfilter/ebtables.c                |   10 +-
 net/ipv4/netfilter/ip_tables.c                 |    8 +-
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |    2 +-
 net/ipv4/netfilter/nf_conntrack_proto_icmp.c   |   11 +-
 net/ipv4/netfilter/nf_defrag_ipv4.c            |    9 +-
 net/ipv4/netfilter/nf_nat_core.c               |   23 ++--
 net/ipv4/netfilter/nf_nat_pptp.c               |    3 +-
 net/ipv6/netfilter/ip6_tables.c                |    8 +-
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |    9 +-
 net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c |   11 +-
 net/netfilter/Kconfig                          |   15 ++
 net/netfilter/Makefile                         |    1 +
 net/netfilter/nf_conntrack_core.c              |  164 +++++++++++++++++-------
 net/netfilter/nf_conntrack_expect.c            |   21 ++-
 net/netfilter/nf_conntrack_h323_main.c         |    3 +-
 net/netfilter/nf_conntrack_helper.c            |   44 ++++++-
 net/netfilter/nf_conntrack_netlink.c           |  125 +++++++++++++-----
 net/netfilter/nf_conntrack_pptp.c              |   14 +-
 net/netfilter/nf_conntrack_proto_dccp.c        |    5 +-
 net/netfilter/nf_conntrack_proto_gre.c         |    2 +-
 net/netfilter/nf_conntrack_proto_sctp.c        |    2 +-
 net/netfilter/nf_conntrack_proto_tcp.c         |    4 +-
 net/netfilter/nf_conntrack_proto_udp.c         |    6 +-
 net/netfilter/nf_conntrack_proto_udplite.c     |    4 +-
 net/netfilter/nf_conntrack_sip.c               |    3 +-
 net/netfilter/nf_conntrack_standalone.c        |    6 +
 net/netfilter/xt_CT.c                          |  147 +++++++++++++++++++++
 net/netfilter/xt_connlimit.c                   |    2 +-
 42 files changed, 628 insertions(+), 190 deletions(-)
 create mode 100644 include/linux/netfilter/xt_CT.h
 create mode 100644 include/net/netfilter/nf_conntrack_zones.h
 create mode 100644 net/netfilter/xt_CT.c

Patrick McHardy (9):
netfilter: add struct net * to target parameters
netfilter: nf_conntrack: split up IPCT_STATUS event
netfilter: ctnetlink: support selective event delivery
netfilter: ctnetlink: only assign helpers for matching protocols
netfilter: nf_conntrack: support conntrack templates
netfilter: xtables: add CT target
netfilter: nf_conntrack: pass template to l4proto ->error handler
netfilter: nf_conntrack: add support for "conntrack zones"
netfilter: ctnetlink: add zone support

#1 lore raw

PATCH 1/9 : netfilter: add struct net * to target parameters

commit 22bb6f4df0068c56f0f68c7af3f0bb46415fb425

Author: Patrick McHardy <[email protected]>
Date:   Wed Jan 20 10:53:52 2010 +0100

netfilter: add struct net * to target parameters

include/linux/netfilter/x_tables.h +2 -0
index 3caf5e1..91f14c4 100644
@@ -249,6 +249,7 @@ struct xt_target_param {
  * Other fields see above.
  */
 struct xt_tgchk_param {
+	struct net *net;
 	const char *table;
 	const void *entryinfo;
 	const struct xt_target *target;
@@ -259,6 +260,7 @@ struct xt_tgchk_param {
 
 /* Target destructor parameters */
 struct xt_tgdtor_param {
+	struct net *net;
 	const struct xt_target *target;
 	void *targinfo;
 	u_int8_t family;
net/bridge/netfilter/ebtables.c +6 -4
index 1aa0e4c..12beb58 100644
@@ -579,13 +579,14 @@ ebt_cleanup_match(struct ebt_entry_match *m, struct net *net, unsigned int *i)
 }
 
 static inline int
-ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
+ebt_cleanup_watcher(struct ebt_entry_watcher *w, struct net *net, unsigned int *i)
 {
 	struct xt_tgdtor_param par;
 
 	if (i && (*i)-- == 0)
 		return 1;
 
+	par.net      = net;
 	par.target   = w->u.watcher;
 	par.targinfo = w->data;
 	par.family   = NFPROTO_BRIDGE;
@@ -606,10 +607,11 @@ ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt)
 	/* we're done */
 	if (cnt && (*cnt)-- == 0)
 		return 1;
-	EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
+	EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, NULL);
 	EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, NULL);
 	t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
 
+	par.net      = net;
 	par.target   = t->u.target;
 	par.targinfo = t->data;
 	par.family   = NFPROTO_BRIDGE;
@@ -674,7 +676,7 @@ ebt_check_entry(struct ebt_entry *e,
 	}
 	i = 0;
 
-	mtpar.net	= net;
+	mtpar.net	= tgpar.net       = net;
 	mtpar.table     = tgpar.table     = name;
 	mtpar.entryinfo = tgpar.entryinfo = e;
 	mtpar.hook_mask = tgpar.hook_mask = hookmask;
@@ -730,7 +732,7 @@ ebt_check_entry(struct ebt_entry *e,
 	(*cnt)++;
 	return 0;
 cleanup_watchers:
-	EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
+	EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, &j);
 cleanup_matches:
 	EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, &i);
 	return ret;
net/ipv4/netfilter/ip_tables.c +5 -3
index cfaba0e..7fde8f6 100644
@@ -638,10 +638,11 @@ err:
 	return ret;
 }
 
-static int check_target(struct ipt_entry *e, const char *name)
+static int check_target(struct ipt_entry *e, struct net *net, const char *name)
 {
 	struct ipt_entry_target *t = ipt_get_target(e);
 	struct xt_tgchk_param par = {
+		.net       = net,
 		.table     = name,
 		.entryinfo = e,
 		.target    = t->u.kernel.target,
@@ -697,7 +698,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
 	}
 	t->u.kernel.target = target;
 
-	ret = check_target(e, name);
+	ret = check_target(e, net, name);
 	if (ret)
 		goto err;
 
@@ -788,6 +789,7 @@ cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i)
 	IPT_MATCH_ITERATE(e, cleanup_match, net, NULL);
 	t = ipt_get_target(e);
 
+	par.net      = net;
 	par.target   = t->u.kernel.target;
 	par.targinfo = t->data;
 	par.family   = NFPROTO_IPV4;
@@ -1675,7 +1677,7 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name,
 	if (ret)
 		goto cleanup_matches;
 
-	ret = check_target(e, name);
+	ret = check_target(e, net, name);
 	if (ret)
 		goto cleanup_matches;
 
net/ipv6/netfilter/ip6_tables.c +5 -3
index 9f1d45f..0376ed6 100644
@@ -669,10 +669,11 @@ err:
 	return ret;
 }
 
-static int check_target(struct ip6t_entry *e, const char *name)
+static int check_target(struct ip6t_entry *e, struct net *net, const char *name)
 {
 	struct ip6t_entry_target *t = ip6t_get_target(e);
 	struct xt_tgchk_param par = {
+		.net       = net,
 		.table     = name,
 		.entryinfo = e,
 		.target    = t->u.kernel.target,
@@ -729,7 +730,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
 	}
 	t->u.kernel.target = target;
 
-	ret = check_target(e, name);
+	ret = check_target(e, net, name);
 	if (ret)
 		goto err;
 
@@ -820,6 +821,7 @@ cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i)
 	IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL);
 	t = ip6t_get_target(e);
 
+	par.net      = net;
 	par.target   = t->u.kernel.target;
 	par.targinfo = t->data;
 	par.family   = NFPROTO_IPV6;
@@ -1710,7 +1712,7 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
 	if (ret)
 		goto cleanup_matches;
 
-	ret = check_target(e, name);
+	ret = check_target(e, net, name);
 	if (ret)
 		goto cleanup_matches;
 
#2 lore raw

PATCH 2/9 : netfilter: nf_conntrack: split up IPCT_STATUS event

In reply to Patrick McHardy

commit 036e308d769fb3191253e954ec17da5455da5420

Author: Patrick McHardy <[email protected]>
Date:   Wed Jan 20 11:38:28 2010 +0100

netfilter: nf_conntrack: split up IPCT_STATUS event

Split up the IPCT_STATUS event into an IPCT_REPLY event, which is generated when the IPS_SEEN_REPLY bit is set, and an IPCT_ASSURED event, which is generated when the IPS_ASSURED bit is set.

In combination with a following patch to support selective event delivery, this can be used for "sparse" conntrack replication: start replicating the conntrack entry after it reached the ASSURED state and that way it's SYN-flood resistant.

include/net/netfilter/nf_conntrack_ecache.h +11 -10
index 475facc..5e05fb8 100644
@@ -14,19 +14,20 @@
 
 /* Connection tracking event types */
 enum ip_conntrack_events {
-	IPCT_NEW		= 0,	/* new conntrack */
-	IPCT_RELATED		= 1,	/* related conntrack */
-	IPCT_DESTROY		= 2,	/* destroyed conntrack */
-	IPCT_STATUS		= 3,	/* status has changed */
-	IPCT_PROTOINFO		= 4,	/* protocol information has changed */
-	IPCT_HELPER		= 5,	/* new helper has been set */
-	IPCT_MARK		= 6,	/* new mark has been set */
-	IPCT_NATSEQADJ		= 7,	/* NAT is doing sequence adjustment */
-	IPCT_SECMARK		= 8,	/* new security mark has been set */
+	IPCT_NEW,		/* new conntrack */
+	IPCT_RELATED,		/* related conntrack */
+	IPCT_DESTROY,		/* destroyed conntrack */
+	IPCT_REPLY,		/* connection has seen two-way traffic */
+	IPCT_ASSURED,		/* connection status has changed to assured */
+	IPCT_PROTOINFO,		/* protocol information has changed */
+	IPCT_HELPER,		/* new helper has been set */
+	IPCT_MARK,		/* new mark has been set */
+	IPCT_NATSEQADJ,		/* NAT is doing sequence adjustment */
+	IPCT_SECMARK,		/* new security mark has been set */
 };
 
 enum ip_conntrack_expect_events {
-	IPEXP_NEW		= 0,	/* new expectation */
+	IPEXP_NEW,		/* new expectation */
 };
 
 struct nf_conntrack_ecache {
net/netfilter/nf_conntrack_core.c +1 -1
index 0e98c32..091ff77 100644
@@ -825,7 +825,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
 	}
 
 	if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
-		nf_conntrack_event_cache(IPCT_STATUS, ct);
+		nf_conntrack_event_cache(IPCT_REPLY, ct);
 
 	return ret;
 }
net/netfilter/nf_conntrack_netlink.c +4 -2
index 79478df..73ff79b 100644
@@ -1366,7 +1366,8 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
 			else
 				events = IPCT_NEW;
 
-			nf_conntrack_eventmask_report((1 << IPCT_STATUS) |
+			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
+						      (1 << IPCT_ASSURED) |
 						      (1 << IPCT_HELPER) |
 						      (1 << IPCT_PROTOINFO) |
 						      (1 << IPCT_NATSEQADJ) |
@@ -1391,7 +1392,8 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
 		if (err == 0) {
 			nf_conntrack_get(&ct->ct_general);
 			spin_unlock_bh(&nf_conntrack_lock);
-			nf_conntrack_eventmask_report((1 << IPCT_STATUS) |
+			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
+						      (1 << IPCT_ASSURED) |
 						      (1 << IPCT_HELPER) |
 						      (1 << IPCT_PROTOINFO) |
 						      (1 << IPCT_NATSEQADJ) |
net/netfilter/nf_conntrack_proto_gre.c +1 -1
index c99cfba..d899b1a 100644
@@ -241,7 +241,7 @@ static int gre_packet(struct nf_conn *ct,
 				   ct->proto.gre.stream_timeout);
 		/* Also, more likely to be important, and not a probe. */
 		set_bit(IPS_ASSURED_BIT, &ct->status);
-		nf_conntrack_event_cache(IPCT_STATUS, ct);
+		nf_conntrack_event_cache(IPCT_ASSURED, ct);
 	} else
 		nf_ct_refresh_acct(ct, ctinfo, skb,
 				   ct->proto.gre.timeout);
net/netfilter/nf_conntrack_proto_sctp.c +1 -1
index f9d930f..b68ff15 100644
@@ -377,7 +377,7 @@ static int sctp_packet(struct nf_conn *ct,
 	    new_state == SCTP_CONNTRACK_ESTABLISHED) {
 		pr_debug("Setting assured bit\n");
 		set_bit(IPS_ASSURED_BIT, &ct->status);
-		nf_conntrack_event_cache(IPCT_STATUS, ct);
+		nf_conntrack_event_cache(IPCT_ASSURED, ct);
 	}
 
 	return NF_ACCEPT;
net/netfilter/nf_conntrack_proto_tcp.c +1 -1
index 3c96437..ad11805 100644
@@ -1045,7 +1045,7 @@ static int tcp_packet(struct nf_conn *ct,
 		   after SYN_RECV or a valid answer for a picked up
 		   connection. */
 		set_bit(IPS_ASSURED_BIT, &ct->status);
-		nf_conntrack_event_cache(IPCT_STATUS, ct);
+		nf_conntrack_event_cache(IPCT_ASSURED, ct);
 	}
 	nf_ct_refresh_acct(ct, ctinfo, skb, timeout);
 
net/netfilter/nf_conntrack_proto_udp.c +1 -1
index 5c5518b..8d38f9a 100644
@@ -77,7 +77,7 @@ static int udp_packet(struct nf_conn *ct,
 		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream);
 		/* Also, more likely to be important, and not a probe */
 		if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
-			nf_conntrack_event_cache(IPCT_STATUS, ct);
+			nf_conntrack_event_cache(IPCT_ASSURED, ct);
 	} else
 		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout);
 
net/netfilter/nf_conntrack_proto_udplite.c +1 -1
index 458655b..0b1bc9b 100644
@@ -75,7 +75,7 @@ static int udplite_packet(struct nf_conn *ct,
 				   nf_ct_udplite_timeout_stream);
 		/* Also, more likely to be important, and not a probe */
 		if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
-			nf_conntrack_event_cache(IPCT_STATUS, ct);
+			nf_conntrack_event_cache(IPCT_ASSURED, ct);
 	} else
 		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udplite_timeout);
 
#3 lore raw

PATCH 3/9 : netfilter: ctnetlink: support selective event delivery

In reply to Patrick McHardy

commit 1ffde83b6b84de4e07676878f3e9f9ee9d257054

Author: Patrick McHardy <[email protected]>
Date:   Mon Jan 25 15:25:03 2010 +0100

netfilter: ctnetlink: support selective event delivery

Add two masks for conntrack end expectation events to struct nf_conntrack_ecache and use them to filter events. Their default value is "all events" when the event sysctl is on and "no events" when it is off. A following patch will add specific initializations. Expectation events depend on the ecache struct of their master conntrack.

include/linux/netfilter/nf_conntrack_common.h +18 -0
index a374787..ebfed90 100644
@@ -74,6 +74,24 @@ enum ip_conntrack_status {
 	IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
 };
 
+/* Connection tracking event types */
+enum ip_conntrack_events {
+	IPCT_NEW,		/* new conntrack */
+	IPCT_RELATED,		/* related conntrack */
+	IPCT_DESTROY,		/* destroyed conntrack */
+	IPCT_REPLY,		/* connection has seen two-way traffic */
+	IPCT_ASSURED,		/* connection status has changed to assured */
+	IPCT_PROTOINFO,		/* protocol information has changed */
+	IPCT_HELPER,		/* new helper has been set */
+	IPCT_MARK,		/* new mark has been set */
+	IPCT_NATSEQADJ,		/* NAT is doing sequence adjustment */
+	IPCT_SECMARK,		/* new security mark has been set */
+};
+
+enum ip_conntrack_expect_events {
+	IPEXP_NEW,		/* new expectation */
+};
+
 #ifdef __KERNEL__
 struct ip_conntrack_stat {
 	unsigned int searched;
include/net/netfilter/nf_conntrack_ecache.h +28 -31

116 lines not on this page · raw message

net/netfilter/nf_conntrack_core.c +1 -1
index 091ff77..53b8da6 100644
@@ -648,7 +648,7 @@ init_conntrack(struct net *net,
 	}
 
 	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
-	nf_ct_ecache_ext_add(ct, GFP_ATOMIC);
+	nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
 
 	spin_lock_bh(&nf_conntrack_lock);
 	exp = nf_ct_find_expectation(net, tuple);
net/netfilter/nf_conntrack_netlink.c +1 -1
index 73ff79b..20e49ab 100644
@@ -1276,7 +1276,7 @@ ctnetlink_create_conntrack(struct net *net,
 	}
 
 	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
-	nf_ct_ecache_ext_add(ct, GFP_ATOMIC);
+	nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
 
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK])
#4 lore raw

PATCH 4/9 : netfilter: ctnetlink: only assign helpers for matching protocols

In reply to Patrick McHardy

commit 60fe6090ad2193a24263a6366675f2d96608a798

Author: Patrick McHardy <[email protected]>
Date:   Mon Jan 25 15:25:03 2010 +0100

netfilter: ctnetlink: only assign helpers for matching protocols

Make sure not to assign a helper for a different network or transport layer protocol to a connection.

Additionally change expectation deletion by helper to compare the name directly - there might be multiple helper registrations using the same name, currently one of them is chosen in an unpredictable manner and only those expectations are removed.

include/net/netfilter/nf_conntrack_helper.h +1 -1
index d015de9..86be7c4 100644
@@ -40,7 +40,7 @@ struct nf_conntrack_helper {
 };
 
 extern struct nf_conntrack_helper *
-__nf_conntrack_helper_find_byname(const char *name);
+__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum);
 
 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
 extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
net/netfilter/nf_conntrack_helper.c +5 -3
index 65c2a7b..c0e461f 100644
@@ -65,7 +65,7 @@ __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
 }
 
 struct nf_conntrack_helper *
-__nf_conntrack_helper_find_byname(const char *name)
+__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
 {
 	struct nf_conntrack_helper *h;
 	struct hlist_node *n;
@@ -73,13 +73,15 @@ __nf_conntrack_helper_find_byname(const char *name)
 
 	for (i = 0; i < nf_ct_helper_hsize; i++) {
 		hlist_for_each_entry_rcu(h, n, &nf_ct_helper_hash[i], hnode) {
-			if (!strcmp(h->name, name))
+			if (!strcmp(h->name, name) &&
+			    h->tuple.src.l3num == l3num &&
+			    h->tuple.dst.protonum == protonum)
 				return h;
 		}
 	}
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname);
+EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find);
 
 struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
 {
net/netfilter/nf_conntrack_netlink.c +11 -12
index 20e49ab..f5c0b09 100644
@@ -1001,7 +1001,8 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
 		return 0;
 	}
 
-	helper = __nf_conntrack_helper_find_byname(helpname);
+	helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
+					    nf_ct_protonum(ct));
 	if (helper == NULL) {
 #ifdef CONFIG_MODULES
 		spin_unlock_bh(&nf_conntrack_lock);
@@ -1012,7 +1013,8 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
 		}
 
 		spin_lock_bh(&nf_conntrack_lock);
-		helper = __nf_conntrack_helper_find_byname(helpname);
+		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
+						    nf_ct_protonum(ct));
 		if (helper)
 			return -EAGAIN;
 #endif
@@ -1211,7 +1213,8 @@ ctnetlink_create_conntrack(struct net *net,
  		if (err < 0)
 			goto err2;
 
-		helper = __nf_conntrack_helper_find_byname(helpname);
+		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
+						    nf_ct_protonum(ct));
 		if (helper == NULL) {
 			rcu_read_unlock();
 #ifdef CONFIG_MODULES
@@ -1221,7 +1224,9 @@ ctnetlink_create_conntrack(struct net *net,
 			}
 
 			rcu_read_lock();
-			helper = __nf_conntrack_helper_find_byname(helpname);
+			helper = __nf_conntrack_helper_find(helpname,
+							    nf_ct_l3num(ct),
+							    nf_ct_protonum(ct));
 			if (helper) {
 				err = -EAGAIN;
 				goto err2;
@@ -1716,7 +1721,6 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
 	struct net *net = sock_net(ctnl);
 	struct nf_conntrack_expect *exp;
 	struct nf_conntrack_tuple tuple;
-	struct nf_conntrack_helper *h;
 	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	struct hlist_node *n, *next;
 	u_int8_t u3 = nfmsg->nfgen_family;
@@ -1753,18 +1757,13 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
 
 		/* delete all expectations for this helper */
 		spin_lock_bh(&nf_conntrack_lock);
-		h = __nf_conntrack_helper_find_byname(name);
-		if (!h) {
-			spin_unlock_bh(&nf_conntrack_lock);
-			return -EOPNOTSUPP;
-		}
 		for (i = 0; i < nf_ct_expect_hsize; i++) {
 			hlist_for_each_entry_safe(exp, n, next,
 						  &net->ct.expect_hash[i],
 						  hnode) {
 				m_help = nfct_help(exp->master);
-				if (m_help->helper == h
-				    && del_timer(&exp->timeout)) {
+				if (!strcmp(m_help->helper->name, name) &&
+				    del_timer(&exp->timeout)) {
 					nf_ct_unlink_expect(exp);
 					nf_ct_expect_put(exp);
 				}
#5 lore raw

PATCH 5/9 : netfilter: nf_conntrack: support conntrack templates

In reply to Patrick McHardy

commit 5c403d5f04276db8f1288cf1a7ad6e675234e31f

Author: Patrick McHardy <[email protected]>
Date:   Mon Jan 25 15:25:04 2010 +0100

netfilter: nf_conntrack: support conntrack templates

Support initializing selected parameters of new conntrack entries from a "conntrack template", which is a specially marked conntrack entry attached to the skb.

Currently the helper and the event delivery masks can be initialized this way.

include/linux/netfilter/nf_conntrack_common.h +4 -0
index ebfed90..c608677 100644
@@ -72,6 +72,10 @@ enum ip_conntrack_status {
 	/* Connection has fixed timeout. */
 	IPS_FIXED_TIMEOUT_BIT = 10,
 	IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
+
+	/* Conntrack is a template */
+	IPS_TEMPLATE_BIT = 11,
+	IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT),
 };
 
 /* Connection tracking event types */
include/net/netfilter/nf_conntrack_helper.h +2 -1
index 86be7c4..e17aaa3 100644
@@ -47,7 +47,8 @@ extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
 
 extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
 
-extern int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags);
+extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
+				     gfp_t flags);
 
 extern void nf_ct_helper_destroy(struct nf_conn *ct);
 
net/netfilter/nf_conntrack_core.c +34 -16

139 lines not on this page · raw message

net/netfilter/nf_conntrack_helper.c +13 -4
index c0e461f..8144b0d 100644
@@ -96,13 +96,22 @@ struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
 
-int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags)
+int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
+			      gfp_t flags)
 {
+	struct nf_conntrack_helper *helper = NULL;
+	struct nf_conn_help *help;
 	int ret = 0;
-	struct nf_conntrack_helper *helper;
-	struct nf_conn_help *help = nfct_help(ct);
 
-	helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+	if (tmpl != NULL) {
+		help = nfct_help(tmpl);
+		if (help != NULL)
+			helper = help->helper;
+	}
+
+	help = nfct_help(ct);
+	if (helper == NULL)
+		helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 	if (helper == NULL) {
 		if (help)
 			rcu_assign_pointer(help->helper, NULL);
net/netfilter/nf_conntrack_netlink.c +1 -1
index f5c0b09..09044f9 100644
@@ -1249,7 +1249,7 @@ ctnetlink_create_conntrack(struct net *net,
 		}
 	} else {
 		/* try an implicit helper assignation */
-		err = __nf_ct_try_assign_helper(ct, GFP_ATOMIC);
+		err = __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
 		if (err < 0)
 			goto err2;
 	}
#6 lore raw

PATCH 6/9 : netfilter: xtables: add CT target

In reply to Patrick McHardy

commit b5d677bfd7e8a26652c83df29c2375161cecd958

Author: Patrick McHardy <[email protected]>
Date:   Mon Jan 25 15:25:04 2010 +0100

netfilter: xtables: add CT target

Add a new target for the raw table, which can be used to specify conntrack parameters for specific connections, f.i. the conntrack helper.

The target attaches a "template" connection tracking entry to the skb, which is used by the conntrack core when initializing the new conntrack.

include/linux/netfilter/xt_CT.h new file +13 -0
new file mode 100644
index 0000000..a4c1880
@@ -0,0 +1,13 @@
+#ifndef _XT_CT_H
+#define _XT_CT_H
+
+struct xt_ct_target_info {
+	u_int32_t	ct_events;
+	u_int32_t	exp_events;
+	char		helper[16];
+
+	/* Used internally by the kernel */
+	struct nf_conn	*ct __attribute__((aligned(8)));
+};
+
+#endif /* _XT_CT_H */
include/net/netfilter/nf_conntrack_helper.h +3 -0
index e17aaa3..32c305d 100644
@@ -42,6 +42,9 @@ struct nf_conntrack_helper {
 extern struct nf_conntrack_helper *
 __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum);
 
+extern struct nf_conntrack_helper *
+nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum);
+
 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
 extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
 
net/netfilter/Kconfig +6 -0
index 634d14a..710a33b 100644
@@ -341,6 +341,12 @@ config NETFILTER_XT_TARGET_CONNSECMARK
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_TARGET_CT
+	tristate '"CT" target support'
+	depends on NF_CONNTRACK
+	depends on IP_NF_RAW || IP6_NF_RAW
+	depends on NETFILTER_ADVANCED
+
 config NETFILTER_XT_TARGET_DSCP
 	tristate '"DSCP" and "TOS" target support'
 	depends on IP_NF_MANGLE || IP6_NF_MANGLE
net/netfilter/Makefile +1 -0
index 49f62ee..f873644 100644
@@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
net/netfilter/nf_conntrack_helper.c +19 -0
index 8144b0d..a74a576 100644
@@ -83,6 +83,25 @@ __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
 }
 EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find);
 
+struct nf_conntrack_helper *
+nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
+{
+	struct nf_conntrack_helper *h;
+
+	h = __nf_conntrack_helper_find(name, l3num, protonum);
+#ifdef CONFIG_MODULES
+	if (h == NULL) {
+		if (request_module("nfct-helper-%s", name) == 0)
+			h = __nf_conntrack_helper_find(name, l3num, protonum);
+	}
+#endif
+	if (h != NULL && !try_module_get(h->me))
+		h = NULL;
+
+	return h;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
+
 struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
 {
 	struct nf_conn_help *help;
net/netfilter/xt_CT.c new file +142 -0

142 lines not on this page · raw message

#7 lore raw

Re: [PATCH 06/09]: netfilter: xtables: add CT target

Quoted 8 lines · Patrick McHardy

netfilter: xtables: add CT target

Add a new target for the raw table, which can be used to specify conntrack parameters for specific connections, f.i. the conntrack helper.

The target attaches a "template" connection tracking entry to the skb, which is used by the conntrack core when initializing the new conntrack.

Quoted 7 lines
include/linux/netfilter/xt_CT.h             |   13 ++
include/net/netfilter/nf_conntrack_helper.h |    3 
net/netfilter/Kconfig                       |    6 +
net/netfilter/Makefile                      |    1 
net/netfilter/nf_conntrack_helper.c         |   19 +++
net/netfilter/xt_CT.c                       |  142 ++++++++++++++++++++++++++++
6 files changed, 184 insertions(+)

Is it perhaps feasible to put the xt_CT code into an already existing .c file (e.g. xt_conntrack.c) to cut on module overhead?

#8 lore raw

Re: [PATCH 06/09]: netfilter: xtables: add CT target

Quoted 18 lines · Jan Engelhardt
Quoted 8 lines · Patrick McHardy

netfilter: xtables: add CT target

Add a new target for the raw table, which can be used to specify conntrack parameters for specific connections, f.i. the conntrack helper.

The target attaches a "template" connection tracking entry to the skb, which is used by the conntrack core when initializing the new conntrack.

Quoted 7 lines
include/linux/netfilter/xt_CT.h             |   13 ++
include/net/netfilter/nf_conntrack_helper.h |    3 
net/netfilter/Kconfig                       |    6 +
net/netfilter/Makefile                      |    1 
net/netfilter/nf_conntrack_helper.c         |   19 +++
net/netfilter/xt_CT.c                       |  142 ++++++++++++++++++++++++++++
6 files changed, 184 insertions(+)
Quoted 2 lines

Is it perhaps feasible to put the xt_CT code into an already existing .c file (e.g. xt_conntrack.c) to cut on module overhead?

They're quite different, so those two don't fit together very well. We could add NOTRACK support to xt_CT and deprecate the NOTRACK module.

#9 lore raw

Re: [PATCH 06/09]: netfilter: xtables: add CT target

Quoted 19 lines · Patrick McHardy
Quoted 18 lines · Jan Engelhardt
Quoted 15 lines · Patrick McHardy

netfilter: xtables: add CT target

Add a new target for the raw table, which can be used to specify conntrack parameters for specific connections, f.i. the conntrack helper.

The target attaches a "template" connection tracking entry to the skb, which is used by the conntrack core when initializing the new conntrack.

include/linux/netfilter/xt_CT.h             |   13 ++
include/net/netfilter/nf_conntrack_helper.h |    3 
net/netfilter/Kconfig                       |    6 +
net/netfilter/Makefile                      |    1 
net/netfilter/nf_conntrack_helper.c         |   19 +++
net/netfilter/xt_CT.c                       |  142 ++++++++++++++++++++++++++++
6 files changed, 184 insertions(+)
Quoted 6 lines
Quoted 2 lines

Is it perhaps feasible to put the xt_CT code into an already existing .c file (e.g. xt_conntrack.c) to cut on module overhead?

They're quite different, so those two don't fit together very well. We could add NOTRACK support to xt_CT and deprecate the NOTRACK module.

Sounds like a plan. Will you take care of that, or should I add it to my list?

#10 lore raw

Re: [PATCH 06/09]: netfilter: xtables: add CT target

Quoted 18 lines · Jan Engelhardt
Quoted 17 lines · Patrick McHardy
Quoted 16 lines · Jan Engelhardt
Quoted 14 lines · Patrick McHardy

netfilter: xtables: add CT target

Add a new target for the raw table, which can be used to specify conntrack parameters for specific connections, f.i. the conntrack helper.

The target attaches a "template" connection tracking entry to the skb, which is used by the conntrack core when initializing the new conntrack.

include/linux/netfilter/xt_CT.h             |   13 ++
include/net/netfilter/nf_conntrack_helper.h |    3 
net/netfilter/Kconfig                       |    6 +
net/netfilter/Makefile                      |    1 
net/netfilter/nf_conntrack_helper.c         |   19 +++
net/netfilter/xt_CT.c                       |  142 ++++++++++++++++++++++++++++
6 files changed, 184 insertions(+)
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Is it perhaps feasible to put the xt_CT code into an already existing .c file (e.g. xt_conntrack.c) to cut on module overhead?

They're quite different, so those two don't fit together very well. We could add NOTRACK support to xt_CT and deprecate the NOTRACK module.

Sounds like a plan. Will you take care of that, or should I add it to my list?

I'll take care of it and will include it in the next submission.

Does anyone have an opinion on supporting specifying helper parameters? I'm considering adding something like 5 generically usable u32s and have helpers initialize parameters like FTP "loose" or SIP "direct_media" based on those.

#11 lore raw

Re: [PATCH 06/09]: netfilter: xtables: add CT target

Quoted 6 lines · Patrick McHardy

Does anyone have an opinion on supporting specifying helper parameters? I'm considering adding something like 5 generically usable u32s and have helpers initialize parameters like FTP "loose" or SIP "direct_media" based on those.

Is there a case where someone wants to loosen just half of their FTP connections? Well yes maybe there is, but anyone ever request it?

#12 lore raw

Re: [PATCH 06/09]: netfilter: xtables: add CT target

Quoted 9 lines · Jan Engelhardt
Quoted 5 lines · Patrick McHardy

Does anyone have an opinion on supporting specifying helper parameters? I'm considering adding something like 5 generically usable u32s and have helpers initialize parameters like FTP "loose" or SIP "direct_media" based on those.

Is there a case where someone wants to loosen just half of their FTP connections? Well yes maybe there is, but anyone ever request it?

Not FTP specifically, SIP and H.323 would be the primary use cases. But if the infrastructure is there anyways, we might as well add support for FTP.

#13 lore raw

PATCH 7/9 : netfilter: nf_conntrack: pass template to l4proto ->error handler

In reply to Patrick McHardy

commit 1ce077bf1a71309d206b29a02be326013735faca

Author: Patrick McHardy <[email protected]>
Date:   Mon Jan 25 15:25:04 2010 +0100

netfilter: nf_conntrack: pass template to l4proto ->error handler

The error handlers might need the template to get the conntrack zone introduced in the next patches to perform a conntrack lookup.

include/net/netfilter/nf_conntrack_l4proto.h +2 -2
index ca6dcf3..e3d3ee3 100644
@@ -49,8 +49,8 @@ struct nf_conntrack_l4proto {
 	/* Called when a conntrack entry is destroyed */
 	void (*destroy)(struct nf_conn *ct);
 
-	int (*error)(struct net *net, struct sk_buff *skb, unsigned int dataoff,
-		     enum ip_conntrack_info *ctinfo,
+	int (*error)(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
+		     unsigned int dataoff, enum ip_conntrack_info *ctinfo,
 		     u_int8_t pf, unsigned int hooknum);
 
 	/* Print out the per-protocol part of the tuple. Return like seq_* */
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +2 -1
index 7afd39b..327826a 100644
@@ -163,7 +163,8 @@ icmp_error_message(struct net *net, struct sk_buff *skb,
 
 /* Small and modified version of icmp_rcv */
 static int
-icmp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
+icmp_error(struct net *net, struct nf_conn *tmpl,
+	   struct sk_buff *skb, unsigned int dataoff,
 	   enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum)
 {
 	const struct icmphdr *icmph;
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +2 -1
index c7b8bd1..d772dc2 100644
@@ -179,7 +179,8 @@ icmpv6_error_message(struct net *net,
 }
 
 static int
-icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
+icmpv6_error(struct net *net, struct nf_conn *tmpl,
+	     struct sk_buff *skb, unsigned int dataoff,
 	     enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum)
 {
 	const struct icmp6hdr *icmp6h;
net/netfilter/nf_conntrack_core.c +2 -1
index 19c95ff..b8b52da 100644
@@ -798,7 +798,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
 	 * inverse of the return code tells to the netfilter
 	 * core what to do with the packet. */
 	if (l4proto->error != NULL) {
-		ret = l4proto->error(net, skb, dataoff, &ctinfo, pf, hooknum);
+		ret = l4proto->error(net, tmpl, skb, dataoff, &ctinfo,
+				     pf, hooknum);
 		if (ret <= 0) {
 			NF_CT_STAT_INC_ATOMIC(net, error);
 			NF_CT_STAT_INC_ATOMIC(net, invalid);
net/netfilter/nf_conntrack_proto_dccp.c +3 -2
index dd37550..9a28155 100644
@@ -561,8 +561,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
 	return NF_ACCEPT;
 }
 
-static int dccp_error(struct net *net, struct sk_buff *skb,
-		      unsigned int dataoff, enum ip_conntrack_info *ctinfo,
+static int dccp_error(struct net *net, struct nf_conn *tmpl,
+		      struct sk_buff *skb, unsigned int dataoff,
+		      enum ip_conntrack_info *ctinfo,
 		      u_int8_t pf, unsigned int hooknum)
 {
 	struct dccp_hdr _dh, *dh;
net/netfilter/nf_conntrack_proto_tcp.c +1 -1
index ad11805..9dd8cd4 100644
@@ -760,7 +760,7 @@ static const u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG) + 1] =
 };
 
 /* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c.  */
-static int tcp_error(struct net *net,
+static int tcp_error(struct net *net, struct nf_conn *tmpl,
 		     struct sk_buff *skb,
 		     unsigned int dataoff,
 		     enum ip_conntrack_info *ctinfo,
net/netfilter/nf_conntrack_proto_udp.c +2 -2
index 8d38f9a..8289088 100644
@@ -91,8 +91,8 @@ static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
 	return true;
 }
 
-static int udp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
-		     enum ip_conntrack_info *ctinfo,
+static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
+		     unsigned int dataoff, enum ip_conntrack_info *ctinfo,
 		     u_int8_t pf,
 		     unsigned int hooknum)
 {
net/netfilter/nf_conntrack_proto_udplite.c +1 -1
index 0b1bc9b..263b5a7 100644
@@ -89,7 +89,7 @@ static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
 	return true;
 }
 
-static int udplite_error(struct net *net,
+static int udplite_error(struct net *net, struct nf_conn *tmpl,
 			 struct sk_buff *skb,
 			 unsigned int dataoff,
 			 enum ip_conntrack_info *ctinfo,
#14 lore raw

PATCH 8/9 : netfilter: nf_conntrack: add support for "conntrack zones"

In reply to Patrick McHardy

commit 9a53ed59344fe3874d157257c80d7fb1c949a316

Author: Patrick McHardy <[email protected]>
Date:   Mon Jan 25 16:21:52 2010 +0100

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:

# assign connections between veth0 and veth1 to conntrack zone 1:

iptables -t raw -I PREROUTING -i veth0 -j CT --zone 1 iptables -t raw -I PREROUTING -i veth1 -j CT --zone 1

include/linux/netfilter/xt_CT.h +1 -0
index a4c1880..fe4ee76 100644
@@ -5,6 +5,7 @@ struct xt_ct_target_info {
 	u_int32_t	ct_events;
 	u_int32_t	exp_events;
 	char		helper[16];
+	u_int16_t	zone;
 
 	/* Used internally by the kernel */
 	struct nf_conn	*ct __attribute__((aligned(8)));
include/net/ip.h +3 -0
index 85108cf..61aface 100644
@@ -336,8 +336,11 @@ enum ip_defrag_users {
 	IP_DEFRAG_LOCAL_DELIVER,
 	IP_DEFRAG_CALL_RA_CHAIN,
 	IP_DEFRAG_CONNTRACK_IN,
+	__IP_DEFRAG_CONNTRACK_IN_END	= IP_DEFRAG_CONNTRACK_IN + 0xffff,
 	IP_DEFRAG_CONNTRACK_OUT,
+	__IP_DEFRAG_CONNTRACK_OUT_END	= IP_DEFRAG_CONNTRACK_OUT + 0xffff,
 	IP_DEFRAG_CONNTRACK_BRIDGE_IN,
+	__IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + 0xffff,
 	IP_DEFRAG_VS_IN,
 	IP_DEFRAG_VS_OUT,
 	IP_DEFRAG_VS_FWD
include/net/ipv6.h +3 -0
index 299bbf5..db422f3 100644
@@ -355,8 +355,11 @@ struct inet_frag_queue;
 enum ip6_defrag_users {
 	IP6_DEFRAG_LOCAL_DELIVER,
 	IP6_DEFRAG_CONNTRACK_IN,
+	__IP6_DEFRAG_CONNTRACK_IN	= IP6_DEFRAG_CONNTRACK_IN + 0xffff,
 	IP6_DEFRAG_CONNTRACK_OUT,
+	__IP6_DEFRAG_CONNTRACK_OUT	= IP6_DEFRAG_CONNTRACK_OUT + 0xffff,
 	IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
+	__IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + 0xffff,
 };
 
 struct ip6_create_arg {
include/net/netfilter/nf_conntrack.h +3 -2
index a0904ad..9488ac6 100644
@@ -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 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_ct_delete_from_lists(struct nf_conn *ct);
@@ -267,7 +268,7 @@ extern void
 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 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 *repl,
 		   gfp_t gfp);
include/net/netfilter/nf_conntrack_core.h +2 -1
index 5a449b4..dffde8e 100644
@@ -49,7 +49,8 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
 
 /* Find a connection corresponding to a tuple. */
 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);
 
include/net/netfilter/nf_conntrack_expect.h +6 -3
index 9a2b9cb..83c49f3 100644
@@ -77,13 +77,16 @@ int nf_conntrack_expect_init(struct net *net);
 void nf_conntrack_expect_fini(struct net *net);
 
 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 *
-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 *
-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_remove_expectations(struct nf_conn *ct);
include/net/netfilter/nf_conntrack_extend.h +2 -0
index e192dc1..2d2a1f9 100644
@@ -8,6 +8,7 @@ enum nf_ct_ext_id {
 	NF_CT_EXT_NAT,
 	NF_CT_EXT_ACCT,
 	NF_CT_EXT_ECACHE,
+	NF_CT_EXT_ZONE,
 	NF_CT_EXT_NUM,
 };
 
@@ -15,6 +16,7 @@ enum nf_ct_ext_id {
 #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
 #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
 #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. */
 struct nf_ct_ext {
include/net/netfilter/nf_conntrack_zones.h new file +21 -0
new file mode 100644
index 0000000..31336d2
@@ -0,0 +1,21 @@
+#ifndef _NF_CONNTRACK_ZONES_H
+#define _NF_CONNTRACK_ZONES_H
+
+#include <net/netfilter/nf_conntrack_extend.h>
+
+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 0;
+}
+
+#endif /* _NF_CONNTRACK_ZONES_H */
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +1 -1
index d171b12..9c1560d 100644
@@ -266,7 +266,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
 		return -EINVAL;
 	}
 
-	h = nf_conntrack_find_get(sock_net(sk), &tuple);
+	h = nf_conntrack_find_get(sock_net(sk), 0, &tuple);
 	if (h) {
 		struct sockaddr_in sin;
 		struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +5 -3
index 327826a..19c3d7f 100644
@@ -18,6 +18,7 @@
 #include <net/netfilter/nf_conntrack_tuple.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_zones.h>
 #include <net/netfilter/nf_log.h>
 
 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,
 
 /* Returns conntrack if it dealt with ICMP, and filled in skb fields */
 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,
 		 unsigned int hooknum)
 {
 	struct nf_conntrack_tuple innertuple, origtuple;
 	const struct nf_conntrack_l4proto *innerproto;
 	const struct nf_conntrack_tuple_hash *h;
+	u16 zone = tmpl ? nf_ct_zone(tmpl) : 0;
 
 	NF_CT_ASSERT(skb->nfct == NULL);
 
@@ -146,7 +148,7 @@ icmp_error_message(struct net *net, struct sk_buff *skb,
 
 	*ctinfo = IP_CT_RELATED;
 
-	h = nf_conntrack_find_get(net, &innertuple);
+	h = nf_conntrack_find_get(net, zone, &innertuple);
 	if (!h) {
 		pr_debug("icmp_error_message: no match\n");
 		return -NF_ACCEPT;
@@ -209,7 +211,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl,
 	    icmph->type != ICMP_REDIRECT)
 		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)
net/ipv4/netfilter/nf_defrag_ipv4.c +6 -3
index 331ead3..cecff07 100644
@@ -16,6 +16,7 @@
 
 #include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv4.h>
+#include <net/netfilter/nf_conntrack_zones.h>
 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
 
 /* Returns new sk_buff, or NULL */
@@ -38,15 +39,17 @@ 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,
 					      struct sk_buff *skb)
 {
+	u16 zone = 0;
+
 #ifdef CONFIG_BRIDGE_NETFILTER
 	if (skb->nf_bridge &&
 	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
-		return IP_DEFRAG_CONNTRACK_BRIDGE_IN;
+		return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
 #endif
 	if (hooknum == NF_INET_PRE_ROUTING)
-		return IP_DEFRAG_CONNTRACK_IN;
+		return IP_DEFRAG_CONNTRACK_IN + zone;
 	else
-		return IP_DEFRAG_CONNTRACK_OUT;
+		return IP_DEFRAG_CONNTRACK_OUT + zone;
 }
 
 static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
net/ipv4/netfilter/nf_nat_core.c +13 -10
index fe1a644..64b9979 100644
@@ -30,6 +30,7 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_zones.h>
 
 static DEFINE_SPINLOCK(nf_nat_lock);
 
@@ -72,13 +73,13 @@ EXPORT_SYMBOL_GPL(nf_nat_proto_put);
 
 /* We keep an extra hash for each conntrack, for fast searching. */
 static inline unsigned int
-hash_by_src(const struct nf_conntrack_tuple *tuple)
+hash_by_src(const struct nf_conntrack_tuple *tuple, u16 zone)
 {
 	unsigned int hash;
 
 	/* Original src, to ensure we map it consistently if poss. */
 	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);
 	return ((u64)hash * nf_nat_htable_size) >> 32;
 }
@@ -142,12 +143,12 @@ same_src(const struct nf_conn *ct,
 
 /* Only called for SRC manip */
 static int
-find_appropriate_src(struct net *net,
+find_appropriate_src(struct net *net, u16 zone,
 		     const struct nf_conntrack_tuple *tuple,
 		     struct nf_conntrack_tuple *result,
 		     const struct nf_nat_range *range)
 {
-	unsigned int h = hash_by_src(tuple);
+	unsigned int h = hash_by_src(tuple, zone);
 	const struct nf_conn_nat *nat;
 	const struct nf_conn *ct;
 	const struct hlist_node *n;
@@ -155,7 +156,7 @@ find_appropriate_src(struct net *net,
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) {
 		ct = nat->ct;
-		if (same_src(ct, tuple)) {
+		if (same_src(ct, tuple) && nf_ct_zone(ct) == zone) {
 			/* Copy source part from reply tuple. */
 			nf_ct_invert_tuplepr(result,
 				       &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
@@ -178,7 +179,7 @@ find_appropriate_src(struct net *net,
    the ip with the lowest src-ip/dst-ip/proto usage.
 */
 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_conn *ct,
 		    enum nf_nat_manip_type maniptype)
@@ -212,7 +213,7 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple,
 	maxip = ntohl(range->max_ip);
 	j = jhash_2words((__force u32)tuple->src.u3.ip,
 			 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;
 	*var_ipp = htonl(minip + j);
 }
@@ -232,6 +233,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
 {
 	struct net *net = nf_ct_net(ct);
 	const struct nf_nat_protocol *proto;
+	u16 zone = nf_ct_zone(ct);
 
 	/* 1) If this srcip/proto/src-proto-part is currently mapped,
 	   and that same mapping gives a unique tuple within the given
@@ -242,7 +244,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
 	   manips not an issue.  */
 	if (maniptype == IP_NAT_MANIP_SRC &&
 	    !(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");
 			if (!nf_nat_used_tuple(tuple, ct))
 				return;
@@ -252,7 +254,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
 	/* 2) Select the least-used IP/proto combination in the given
 	   range. */
 	*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
 	   the range to make a unique tuple. */
@@ -330,7 +332,8 @@ nf_nat_setup_info(struct nf_conn *ct,
 	if (have_to_hash) {
 		unsigned int srchash;
 
-		srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+		srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+				      nf_ct_zone(ct));
 		spin_lock_bh(&nf_nat_lock);
 		/* nf_conntrack_alter_reply might re-allocate exntension aera */
 		nat = nfct_nat(ct);
net/ipv4/netfilter/nf_nat_pptp.c +2 -1
index 9eb1710..4c06003 100644
@@ -25,6 +25,7 @@
 #include <net/netfilter/nf_nat_rule.h>
 #include <net/netfilter/nf_conntrack_helper.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_pptp.h>
 
@@ -74,7 +75,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
 
 	pr_debug("trying to unexpect other dir: ");
 	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) {
 		nf_ct_unexpect_related(other_exp);
 		nf_ct_expect_put(other_exp);
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +6 -3
index 0956eba..b4e014f 100644
@@ -27,6 +27,7 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_l3proto.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/nf_log.h>
 
@@ -191,15 +192,17 @@ out:
 static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
 						struct sk_buff *skb)
 {
+	u16 zone = 0;
+
 #ifdef CONFIG_BRIDGE_NETFILTER
 	if (skb->nf_bridge &&
 	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
-		return IP6_DEFRAG_CONNTRACK_BRIDGE_IN;
+		return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
 #endif
 	if (hooknum == NF_INET_PRE_ROUTING)
-		return IP6_DEFRAG_CONNTRACK_IN;
+		return IP6_DEFRAG_CONNTRACK_IN + zone;
 	else
-		return IP6_DEFRAG_CONNTRACK_OUT;
+		return IP6_DEFRAG_CONNTRACK_OUT + zone;
 
 }
 
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +5 -3
index d772dc2..bb4f912 100644
@@ -23,6 +23,7 @@
 #include <net/netfilter/nf_conntrack_tuple.h>
 #include <net/netfilter/nf_conntrack_l4proto.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/nf_log.h>
 
@@ -128,7 +129,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb,
 }
 
 static int
-icmpv6_error_message(struct net *net,
+icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
 		     struct sk_buff *skb,
 		     unsigned int icmp6off,
 		     enum ip_conntrack_info *ctinfo,
@@ -137,6 +138,7 @@ icmpv6_error_message(struct net *net,
 	struct nf_conntrack_tuple intuple, origtuple;
 	const struct nf_conntrack_tuple_hash *h;
 	const struct nf_conntrack_l4proto *inproto;
+	u16 zone = tmpl ? nf_ct_zone(tmpl) : 0;
 
 	NF_CT_ASSERT(skb->nfct == NULL);
 
@@ -163,7 +165,7 @@ icmpv6_error_message(struct net *net,
 
 	*ctinfo = IP_CT_RELATED;
 
-	h = nf_conntrack_find_get(net, &intuple);
+	h = nf_conntrack_find_get(net, zone, &intuple);
 	if (!h) {
 		pr_debug("icmpv6_error: no match\n");
 		return -NF_ACCEPT;
@@ -216,7 +218,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl,
 	if (icmp6h->icmp6_type >= 128)
 		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)
net/netfilter/Kconfig +9 -0
index 710a33b..f1d3883 100644
@@ -83,6 +83,15 @@ config NF_CONNTRACK_SECMARK
 
 	  If unsure, say 'N'.
 
+config NF_CONNTRACK_ZONES
+	bool  'Connection tracking zones'
+	help
+	  This option enables support for connection tracking zones.
+	  Normally, each connection needs to have a unique identity.
+	  Connection tracking zones allow to have multiple connections
+	  using the same identity, as long as they are contained in
+	  different zones.
+
 config NF_CONNTRACK_EVENTS
 	bool "Connection tracking events"
 	depends on NETFILTER_ADVANCED
net/netfilter/nf_conntrack_core.c +82 -27

298 lines not on this page · raw message

net/netfilter/nf_conntrack_expect.c +14 -7
index fdf5d2a..b3052cb 100644
@@ -27,6 +27,7 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
+#include <net/netfilter/nf_conntrack_zones.h>
 
 unsigned int nf_ct_expect_hsize __read_mostly;
 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
 }
 
 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 hlist_node *n;
@@ -95,7 +97,8 @@ __nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple)
 
 	h = nf_ct_expect_dst_hash(tuple);
 	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 NULL;
@@ -104,12 +107,13 @@ EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
 
 /* Just find a expectation corresponding to a tuple. */
 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;
 
 	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))
 		i = NULL;
 	rcu_read_unlock();
@@ -121,7 +125,8 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
 /* If an expectation for this connection is found, it gets delete from
  * global list then returned. */
 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 hlist_node *n;
@@ -133,7 +138,8 @@ nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple)
 	h = nf_ct_expect_dst_hash(tuple);
 	hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
 		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;
 			break;
 		}
@@ -204,7 +210,8 @@ static inline int expect_matches(const struct nf_conntrack_expect *a,
 {
 	return a->master == b->master && a->class == b->class &&
 		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. */
net/netfilter/nf_conntrack_h323_main.c +2 -1
index 6636949..a1c8dd9 100644
@@ -29,6 +29,7 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 #include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_zones.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
 
 /* Parameters */
@@ -1216,7 +1217,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
 	tuple.dst.u.tcp.port = port;
 	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)
 		return exp;
 	return NULL;
net/netfilter/nf_conntrack_netlink.c +10 -10
index 09044f9..1dcd7a0 100644
@@ -796,7 +796,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
 	if (err < 0)
 		return err;
 
-	h = nf_conntrack_find_get(net, &tuple);
+	h = nf_conntrack_find_get(net, 0, &tuple);
 	if (!h)
 		return -ENOENT;
 
@@ -857,7 +857,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 	if (err < 0)
 		return err;
 
-	h = nf_conntrack_find_get(net, &tuple);
+	h = nf_conntrack_find_get(net, 0, &tuple);
 	if (!h)
 		return -ENOENT;
 
@@ -1194,7 +1194,7 @@ ctnetlink_create_conntrack(struct net *net,
 	int err = -EINVAL;
 	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))
 		return ERR_PTR(-ENOMEM);
 
@@ -1298,7 +1298,7 @@ ctnetlink_create_conntrack(struct net *net,
 		if (err < 0)
 			goto err2;
 
-		master_h = nf_conntrack_find_get(net, &master);
+		master_h = nf_conntrack_find_get(net, 0, &master);
 		if (master_h == NULL) {
 			err = -ENOENT;
 			goto err2;
@@ -1347,9 +1347,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
 
 	spin_lock_bh(&nf_conntrack_lock);
 	if (cda[CTA_TUPLE_ORIG])
-		h = __nf_conntrack_find(net, &otuple);
+		h = __nf_conntrack_find(net, 0, &otuple);
 	else if (cda[CTA_TUPLE_REPLY])
-		h = __nf_conntrack_find(net, &rtuple);
+		h = __nf_conntrack_find(net, 0, &rtuple);
 
 	if (h == NULL) {
 		err = -ENOENT;
@@ -1678,7 +1678,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
 	if (err < 0)
 		return err;
 
-	exp = nf_ct_expect_find_get(net, &tuple);
+	exp = nf_ct_expect_find_get(net, 0, &tuple);
 	if (!exp)
 		return -ENOENT;
 
@@ -1734,7 +1734,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
 			return err;
 
 		/* bump usage count to 2 */
-		exp = nf_ct_expect_find_get(net, &tuple);
+		exp = nf_ct_expect_find_get(net, 0, &tuple);
 		if (!exp)
 			return -ENOENT;
 
@@ -1819,7 +1819,7 @@ ctnetlink_create_expect(struct net *net, const struct nlattr * const cda[],
 		return err;
 
 	/* 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)
 		return -ENOENT;
 	ct = nf_ct_tuplehash_to_ctrack(h);
@@ -1876,7 +1876,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
 		return err;
 
 	spin_lock_bh(&nf_conntrack_lock);
-	exp = __nf_ct_expect_find(net, &tuple);
+	exp = __nf_ct_expect_find(net, 0, &tuple);
 
 	if (!exp) {
 		spin_unlock_bh(&nf_conntrack_lock);
net/netfilter/nf_conntrack_pptp.c +8 -6
index 3807ac7..0889448 100644
@@ -28,6 +28,7 @@
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.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_pptp.h>
 
@@ -123,7 +124,7 @@ static void pptp_expectfn(struct nf_conn *ct,
 		pr_debug("trying to unexpect other dir: ");
 		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) {
 			/* delete other expectation.  */
 			pr_debug("found\n");
@@ -136,17 +137,18 @@ static void pptp_expectfn(struct nf_conn *ct,
 	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_hash *h;
 	struct nf_conntrack_expect *exp;
 	struct nf_conn *sibling;
+	u16 zone = nf_ct_zone(ct);
 
 	pr_debug("trying to timeout ct or exp for tuple ");
 	nf_ct_dump_tuple(t);
 
-	h = nf_conntrack_find_get(net, t);
+	h = nf_conntrack_find_get(net, zone, t);
 	if (h)  {
 		sibling = nf_ct_tuplehash_to_ctrack(h);
 		pr_debug("setting timeout of conntrack %p to 0\n", sibling);
@@ -157,7 +159,7 @@ static int destroy_sibling_or_exp(struct net *net,
 		nf_ct_put(sibling);
 		return 1;
 	} else {
-		exp = nf_ct_expect_find_get(net, t);
+		exp = nf_ct_expect_find_get(net, zone, t);
 		if (exp) {
 			pr_debug("unexpect_related of expect %p\n", exp);
 			nf_ct_unexpect_related(exp);
@@ -182,7 +184,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
 	t.dst.protonum = IPPROTO_GRE;
 	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;
-	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");
 
 	/* try reply (pac->pns) tuple */
@@ -190,7 +192,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
 	t.dst.protonum = IPPROTO_GRE;
 	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;
-	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");
 }
 
net/netfilter/nf_conntrack_sip.c +2 -1
index 4b57216..3b5efc9 100644
@@ -22,6 +22,7 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_zones.h>
 #include <linux/netfilter/nf_conntrack_sip.h>
 
 MODULE_LICENSE("GPL");
@@ -777,7 +778,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
 
 	rcu_read_lock();
 	do {
-		exp = __nf_ct_expect_find(net, &tuple);
+		exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
 
 		if (!exp || exp->master == ct ||
 		    nfct_help(exp->master)->helper != nfct_help(ct)->helper ||
net/netfilter/nf_conntrack_standalone.c +6 -0
index 028aba6..4e7dd4f 100644
@@ -26,6 +26,7 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_acct.h>
+#include <net/netfilter/nf_conntrack_zones.h>
 
 MODULE_LICENSE("GPL");
 
@@ -171,6 +172,11 @@ static int ct_seq_show(struct seq_file *s, void *v)
 		goto release;
 #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)))
 		goto release;
 
net/netfilter/xt_CT.c +6 -1
index 55e0713..86a6300 100644
@@ -16,6 +16,7 @@
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_helper.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,
 				 const struct xt_target_param *par)
@@ -57,11 +58,15 @@ static bool xt_ct_tg_check(const struct xt_tgchk_param *par)
 	struct nf_conn *ct;
 	u8 proto;
 
+#ifndef CONFIG_NF_CONNTRACK_ZONES
+	if (info->zone)
+		goto err1;
+#endif
 	if (nf_ct_l3proto_try_module_get(par->family) < 0)
 		goto err1;
 
 	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))
 		goto err2;
 
net/netfilter/xt_connlimit.c +1 -1
index 0d9d18e..0c0cebe 100644
@@ -114,7 +114,7 @@ static int count_them(struct net *net,
 
 	/* check the saved connections */
 	list_for_each_entry_safe(conn, tmp, hash, list) {
-		found    = nf_conntrack_find_get(net, &conn->tuple);
+		found    = nf_conntrack_find_get(net, 0, &conn->tuple);
 		found_ct = NULL;
 
 		if (found != NULL)
#15 lore raw

Re: [PATCH 08/09]: netfilter: nf_conntrack: add support for "conntrack zones"

Quoted 18 lines · Patrick McHardy
include/linux/netfilter/xt_CT.h +1 -0
index a4c1880..fe4ee76 100644
@@ -5,6 +5,7 @@ struct xt_ct_target_info {
 	u_int32_t	ct_events;
 	u_int32_t	exp_events;
 	char		helper[16];
+	u_int16_t	zone;
 
 	/* Used internally by the kernel */
 	struct nf_conn	*ct __attribute__((aligned(8)));
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +0 -0
index d171b12..9c1560d 100644

net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c getorigdst(struct sock *sk, int optval, void __user *user, int *len) · line 269

Quoted 5 lines
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +1 -1
@@ -266,7 +266,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
 		return -EINVAL;
 	}
 
-	h = nf_conntrack_find_get(sock_net(sk), &tuple);
+	h = nf_conntrack_find_get(sock_net(sk), 0, &tuple);

I would prefer to avoid literal numbers where doing so meaningful; perhaps we can introduce a symbolic constant NF_CT_GLOBAL_ZONE or similar here.

#16 lore raw

Re: [PATCH 08/09]: netfilter: nf_conntrack: add support for "conntrack zones"

Quoted 22 lines · Jan Engelhardt
Quoted 21 lines · Patrick McHardy
include/linux/netfilter/xt_CT.h +1 -0
index a4c1880..fe4ee76 100644
@@ -5,6 +5,7 @@ struct xt_ct_target_info {
 	u_int32_t	ct_events;
 	u_int32_t	exp_events;
 	char		helper[16];
+	u_int16_t	zone;
 
 	/* Used internally by the kernel */
 	struct nf_conn	*ct __attribute__((aligned(8)));
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +0 -0
index d171b12..9c1560d 100644
@@ -266,7 +266,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
 		return -EINVAL;
 	}
 
Quoted 6 lines

net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c getorigdst(struct sock *sk, int optval, void __user *user, int *len) · line 269

Quoted 2 lines
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +1 -1
-	h = nf_conntrack_find_get(sock_net(sk), &tuple);
+	h = nf_conntrack_find_get(sock_net(sk), 0, &tuple);

I would prefer to avoid literal numbers where doing so meaningful; perhaps we can introduce a symbolic constant NF_CT_GLOBAL_ZONE or similar here.

Sure, I'll add that.

#17 lore raw

PATCH 9/9 : netfilter: ctnetlink: add zone support

In reply to Patrick McHardy

commit f38b9023022d819503465f9e74dcfad12d85c8b2

Author: Patrick McHardy <[email protected]>
Date:   Mon Jan 25 16:21:58 2010 +0100

netfilter: ctnetlink: add zone support

Parse and dump the conntrack zone in ctnetlink.

include/linux/netfilter/nfnetlink_conntrack.h +2 -0
index ed4ef8d..9ed534c 100644
@@ -40,6 +40,7 @@ enum ctattr_type {
 	CTA_NAT_SEQ_ADJ_ORIG,
 	CTA_NAT_SEQ_ADJ_REPLY,
 	CTA_SECMARK,
+	CTA_ZONE,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
@@ -159,6 +160,7 @@ enum ctattr_expect {
 	CTA_EXPECT_TIMEOUT,
 	CTA_EXPECT_ID,
 	CTA_EXPECT_HELP_NAME,
+	CTA_EXPECT_ZONE,
 	__CTA_EXPECT_MAX
 };
 #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
net/netfilter/nf_conntrack_netlink.c +73 -19

255 lines not on this page · raw message

#18 lore raw
In reply to Patrick McHardy
Quoted 5 lines · Patrick McHardy
include/linux/netfilter/nf_conntrack_common.h  |   22 +++
include/linux/netfilter/nfnetlink_conntrack.h  |    2 +
include/linux/netfilter/x_tables.h             |    2 +
include/linux/netfilter/xt_CT.h                |   14 ++

Is there anything that prohibits using a little-more descriptive name, like xt_CONNTRACK?
That btw reminds me that, perhaps, we could/should avoid same-name different-case (cf. xt_conntrack) in future, so xt_CONNTRACK would not fly too well.

#19 lore raw
Quoted 11 lines · Jan Engelhardt
Quoted 4 lines · Patrick McHardy
include/linux/netfilter/nf_conntrack_common.h  |   22 +++
include/linux/netfilter/nfnetlink_conntrack.h  |    2 +
include/linux/netfilter/x_tables.h             |    2 +
include/linux/netfilter/xt_CT.h                |   14 ++

Is there anything that prohibits using a little-more descriptive name, like xt_CONNTRACK?
That btw reminds me that, perhaps, we could/should avoid same-name different-case (cf. xt_conntrack) in future, so xt_CONNTRACK would not fly too well.

I thought CT is an established term for connection tracking. I don't care much, but I prefer a short name like CT.

#20 lore raw
Quoted 7 lines · Patrick McHardy
Quoted 6 lines · Jan Engelhardt
Quoted 4 lines · Patrick McHardy
include/linux/netfilter/nf_conntrack_common.h  |   22 +++
include/linux/netfilter/nfnetlink_conntrack.h  |    2 +
include/linux/netfilter/x_tables.h             |    2 +
include/linux/netfilter/xt_CT.h                |   14 ++
Quoted 8 lines
Quoted 5 lines

Is there anything that prohibits using a little-more descriptive name, like xt_CONNTRACK?
That btw reminds me that, perhaps, we could/should avoid same-name different-case (cf. xt_conntrack) in future, so xt_CONNTRACK would not fly too well.

I thought CT is an established term for connection tracking. I don't care much, but I prefer a short name like CT.

If you go by the "established" argument, I'd point out "counter-terrorists", but ok ;-)

#21 lore raw
In reply to Patrick McHardy

Hi Patrick,

Sorry for the silence, we're in the exams season since last week and that nuts a lot.

Quoted 7 lines · Patrick McHardy

The following patches contain a new version of the conntrack zones patchset, including a new xtables target to (among other things) assign conntracks to a specific zone, replacing the device attribute used in the previous version.

Quick overview:

Quoted 7 lines

- Patch 1 adds a struct net * parameter to the xtables target parameter structures as preparation for the CT target, which needs to allocate a conntrack entry in the proper namespace

- Patch 2 splits up the IPCT_STATUS event as requested by Jozsef. The CT target can be used for selective conntrack event delivery, this allows more fine grained control over the delivered events.

This is indeed interesting.

Quoted 3 lines

- Patch 3 adds selective conntrack event delivery by adding two masks for conntrack and expectation events to struct nf_conntrack_ecache, which are used to filter out events.

This feature is something that I wanted since time ago. We can reduce the CPU consumption by reducing the amount of events. This is particularly good for ulogd2 and conntrackd.

My experiments showed that the BSF-based filtering does not provide any significant gain from filtering Netlink message in user-space. The problem is that we have to spend cycles building the message which seems to be costly.

AFAICS, this approach has one minor threat since it applies to all processes (I'm sure you're aware of it). I'm fine with this anyway, but maybe we should think of some way to make it per-process at some point? Some netlink unicast-based reporting similar to what NFLOG and NFQUEUE would solve this issue although they are implementing multicast over netlink unicast.

Quoted 15 lines

- Patch 4 fixes ctnetlink to only assign helpers for matching protocols to conntrack entries and fixes expectation deletion by helper name. This is also preparation for the CT target, which can also assign helpers to new connections.

- Patch 5 adds support for conntrack templates, which are specially marked conntrack entries attached to the skb that are used to initialize specific parameters of new connections.

- Patch 6 adds the CT target

- Patch 7 contains preparatory work for assigning conntracks to zones:
the template needs to be passed to L4 ->error handlers for ICMP and ICMPv6 to perform the conntrack lookup in the correct zone

Quoted 6 lines

- Patch 8 adds zone support to nf_conntrack and the CT target. This works by incorporating a numerical "zone" identifier into the conntrack/NAT hashes and comparing it during lookups.

- Patch 9 adds zone support to ctnetlink by dumping and parsing a new CTA_ZONE attribute that contains the zone ID.

This conntrack zone stuff seems interesting. I'll add support for this to libnetfilter_conntrack. Kudos on you.

#22 lore raw
Quoted 36 lines · Pablo Neira Ayuso

Hi Patrick,

Sorry for the silence, we're in the exams season since last week and that nuts a lot.

Quoted 7 lines · Patrick McHardy

The following patches contain a new version of the conntrack zones patchset, including a new xtables target to (among other things) assign conntracks to a specific zone, replacing the device attribute used in the previous version.

Quick overview:

Quoted 7 lines

- Patch 1 adds a struct net * parameter to the xtables target parameter structures as preparation for the CT target, which needs to allocate a conntrack entry in the proper namespace

- Patch 2 splits up the IPCT_STATUS event as requested by Jozsef. The CT target can be used for selective conntrack event delivery, this allows more fine grained control over the delivered events.

This is indeed interesting.

Quoted 3 lines

- Patch 3 adds selective conntrack event delivery by adding two masks for conntrack and expectation events to struct nf_conntrack_ecache, which are used to filter out events.

This feature is something that I wanted since time ago. We can reduce the CPU consumption by reducing the amount of events. This is particularly good for ulogd2 and conntrackd.

My experiments showed that the BSF-based filtering does not provide any significant gain from filtering Netlink message in user-space. The problem is that we have to spend cycles building the message which seems to be costly.

Quoted 6 lines

AFAICS, this approach has one minor threat since it applies to all processes (I'm sure you're aware of it). I'm fine with this anyway, but maybe we should think of some way to make it per-process at some point? Some netlink unicast-based reporting similar to what NFLOG and NFQUEUE would solve this issue although they are implementing multicast over netlink unicast.

The question is whether that would really reduce overhead since we'd like would have to construct messages multiple times ourselves in that case. But yes, it might help.

Quoted 19 lines
Quoted 19 lines

- Patch 4 fixes ctnetlink to only assign helpers for matching protocols to conntrack entries and fixes expectation deletion by helper name. This is also preparation for the CT target, which can also assign helpers to new connections.

- Patch 5 adds support for conntrack templates, which are specially marked conntrack entries attached to the skb that are used to initialize specific parameters of new connections.

- Patch 6 adds the CT target

- Patch 7 contains preparatory work for assigning conntracks to zones:
the template needs to be passed to L4 ->error handlers for ICMP and ICMPv6 to perform the conntrack lookup in the correct zone

- Patch 8 adds zone support to nf_conntrack and the CT target. This works by incorporating a numerical "zone" identifier into the conntrack/NAT hashes and comparing it during lookups.

Quoted 5 lines
Quoted 2 lines

- Patch 9 adds zone support to ctnetlink by dumping and parsing a new CTA_ZONE attribute that contains the zone ID.

This conntrack zone stuff seems interesting. I'll add support for this to libnetfilter_conntrack. Kudos on you.

Great, thanks. I'll probably post a final version within the next two days.

#23 lore raw
Quoted 21 lines · Patrick McHardy
Quoted 13 lines · Pablo Neira Ayuso
Quoted 3 lines

- Patch 3 adds selective conntrack event delivery by adding two masks for conntrack and expectation events to struct nf_conntrack_ecache, which are used to filter out events.

This feature is something that I wanted since time ago. We can reduce the CPU consumption by reducing the amount of events. This is particularly good for ulogd2 and conntrackd.

My experiments showed that the BSF-based filtering does not provide any significant gain from filtering Netlink message in user-space. The problem is that we have to spend cycles building the message which seems to be costly.

Quoted 6 lines

AFAICS, this approach has one minor threat since it applies to all processes (I'm sure you're aware of it). I'm fine with this anyway, but maybe we should think of some way to make it per-process at some point? Some netlink unicast-based reporting similar to what NFLOG and NFQUEUE would solve this issue although they are implementing multicast over netlink unicast.

Quoted 3 lines

The question is whether that would really reduce overhead since we'd like would have to construct messages multiple times ourselves in that case. But yes, it might help.

I think the current way is one of the best: the interesting events are selected by CT, sent to userspace and the userspace processes pick the ones they are interested in. Or do I miss something?

Best regards,
Jozsef
-
E-mail : [email protected], [email protected] PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics

          H-1525 Budapest 114, POB. 49, Hungary