netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nf-next 0/3] netfilter: nftables: add set support for conntrack labels
@ 2015-12-07 12:05 Florian Westphal
  2015-12-07 12:05 ` [PATCH nf-next 1/3] netfilter: connlabels: move helpers to xt_connlabel Florian Westphal
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Florian Westphal @ 2015-12-07 12:05 UTC (permalink / raw)
  To: netfilter-devel

make "add rule filter input ct label set ct label | bar" work.

First patch is a cleanup and moves xt specific code to xt_connlabel.

Second patch is a fix to the clabel replace function to not emit
an event in case old and new are the same (this isn't a problem
for xtables since it doesn't use nf_connlabels_replace).

Last patch adds nft_ct set support.

Let me know if you spot any problems with this approach.
I'm especially interested in the userspace side, see patch
#3 for example.

 include/net/netfilter/nf_conntrack_labels.h |    3 -
 net/netfilter/nf_conntrack_labels.c         |   50 +++++-----------------------
 net/netfilter/nft_ct.c                      |   31 +++++++++++++++++
 net/netfilter/xt_connlabel.c                |   38 ++++++++++++++++++++-
 4 files changed, 77 insertions(+), 45 deletions(-)


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH nf-next 1/3] netfilter: connlabels: move helpers to xt_connlabel
  2015-12-07 12:05 [PATCH nf-next 0/3] netfilter: nftables: add set support for conntrack labels Florian Westphal
@ 2015-12-07 12:05 ` Florian Westphal
  2015-12-07 12:05 ` [PATCH nf-next 2/3] netfilter: labels: don't emit ct event if labels are unchanged Florian Westphal
  2015-12-07 12:05 ` [PATCH nf-next 3/3] netfilter: nftables: add connlabel set support Florian Westphal
  2 siblings, 0 replies; 4+ messages in thread
From: Florian Westphal @ 2015-12-07 12:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Currently labels can only be set either by iptables connlabel
match or via ctnetlink.

Before adding nftables set support, clean up the clabel core and move
helpers that nft will not need after all to the xtables module.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/netfilter/nf_conntrack_labels.h |  3 ---
 net/netfilter/nf_conntrack_labels.c         | 34 --------------------------
 net/netfilter/xt_connlabel.c                | 38 +++++++++++++++++++++++++++--
 3 files changed, 36 insertions(+), 39 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_labels.h b/include/net/netfilter/nf_conntrack_labels.h
index 7e2b1d0..d2ac647 100644
--- a/include/net/netfilter/nf_conntrack_labels.h
+++ b/include/net/netfilter/nf_conntrack_labels.h
@@ -45,9 +45,6 @@ static inline struct nf_conn_labels *nf_ct_labels_ext_add(struct nf_conn *ct)
 #endif
 }
 
-bool nf_connlabel_match(const struct nf_conn *ct, u16 bit);
-int nf_connlabel_set(struct nf_conn *ct, u16 bit);
-
 int nf_connlabels_replace(struct nf_conn *ct,
 			  const u32 *data, const u32 *mask, unsigned int words);
 
diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c
index 3ce5c31..005ddf6 100644
--- a/net/netfilter/nf_conntrack_labels.c
+++ b/net/netfilter/nf_conntrack_labels.c
@@ -16,40 +16,6 @@
 
 static spinlock_t nf_connlabels_lock;
 
-static unsigned int label_bits(const struct nf_conn_labels *l)
-{
-	unsigned int longs = l->words;
-	return longs * BITS_PER_LONG;
-}
-
-bool nf_connlabel_match(const struct nf_conn *ct, u16 bit)
-{
-	struct nf_conn_labels *labels = nf_ct_labels_find(ct);
-
-	if (!labels)
-		return false;
-
-	return bit < label_bits(labels) && test_bit(bit, labels->bits);
-}
-EXPORT_SYMBOL_GPL(nf_connlabel_match);
-
-int nf_connlabel_set(struct nf_conn *ct, u16 bit)
-{
-	struct nf_conn_labels *labels = nf_ct_labels_find(ct);
-
-	if (!labels || bit >= label_bits(labels))
-		return -ENOSPC;
-
-	if (test_bit(bit, labels->bits))
-		return 0;
-
-	if (!test_and_set_bit(bit, labels->bits))
-		nf_conntrack_event_cache(IPCT_LABEL, ct);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(nf_connlabel_set);
-
 static void replace_u32(u32 *address, u32 mask, u32 new)
 {
 	u32 old, tmp;
diff --git a/net/netfilter/xt_connlabel.c b/net/netfilter/xt_connlabel.c
index bb9cbeb..e0679c4 100644
--- a/net/netfilter/xt_connlabel.c
+++ b/net/netfilter/xt_connlabel.c
@@ -10,6 +10,7 @@
 #include <linux/skbuff.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_labels.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
 #include <linux/netfilter/x_tables.h>
 
 MODULE_LICENSE("GPL");
@@ -18,6 +19,39 @@ MODULE_DESCRIPTION("Xtables: add/match connection trackling labels");
 MODULE_ALIAS("ipt_connlabel");
 MODULE_ALIAS("ip6t_connlabel");
 
+static unsigned int label_bits(const struct nf_conn_labels *l)
+{
+	unsigned int longs = l->words;
+
+	return longs * BITS_PER_LONG;
+}
+
+static bool connlabel_match(const struct nf_conn *ct, u16 bit)
+{
+	struct nf_conn_labels *labels = nf_ct_labels_find(ct);
+
+	if (!labels)
+		return false;
+
+	return bit < label_bits(labels) && test_bit(bit, labels->bits);
+}
+
+static int connlabel_set(struct nf_conn *ct, u16 bit)
+{
+	struct nf_conn_labels *labels = nf_ct_labels_find(ct);
+
+	if (!labels || bit >= label_bits(labels))
+		return -ENOSPC;
+
+	if (test_bit(bit, labels->bits))
+		return 0;
+
+	if (!test_and_set_bit(bit, labels->bits))
+		nf_conntrack_event_cache(IPCT_LABEL, ct);
+
+	return 0;
+}
+
 static bool
 connlabel_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
@@ -31,9 +65,9 @@ connlabel_mt(const struct sk_buff *skb, struct xt_action_param *par)
 		return invert;
 
 	if (info->options & XT_CONNLABEL_OP_SET)
-		return (nf_connlabel_set(ct, info->bit) == 0) ^ invert;
+		return (connlabel_set(ct, info->bit) == 0) ^ invert;
 
-	return nf_connlabel_match(ct, info->bit) ^ invert;
+	return connlabel_match(ct, info->bit) ^ invert;
 }
 
 static int connlabel_mt_check(const struct xt_mtchk_param *par)
-- 
2.4.10


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH nf-next 2/3] netfilter: labels: don't emit ct event if labels are unchanged
  2015-12-07 12:05 [PATCH nf-next 0/3] netfilter: nftables: add set support for conntrack labels Florian Westphal
  2015-12-07 12:05 ` [PATCH nf-next 1/3] netfilter: connlabels: move helpers to xt_connlabel Florian Westphal
@ 2015-12-07 12:05 ` Florian Westphal
  2015-12-07 12:05 ` [PATCH nf-next 3/3] netfilter: nftables: add connlabel set support Florian Westphal
  2 siblings, 0 replies; 4+ messages in thread
From: Florian Westphal @ 2015-12-07 12:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

make the replace function only send a ctnetlink event if the contents
of the new set is different.

Otherwise 'ct label set ct label | bar'

will cause netlink event storm since we "replace" labels for each packet.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nf_conntrack_labels.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c
index 005ddf6..46134d0 100644
--- a/net/netfilter/nf_conntrack_labels.c
+++ b/net/netfilter/nf_conntrack_labels.c
@@ -16,14 +16,18 @@
 
 static spinlock_t nf_connlabels_lock;
 
-static void replace_u32(u32 *address, u32 mask, u32 new)
+static int replace_u32(u32 *address, u32 mask, u32 new)
 {
 	u32 old, tmp;
 
 	do {
 		old = *address;
 		tmp = (old & mask) ^ new;
+		if (old == tmp)
+			return 0;
 	} while (cmpxchg(address, old, tmp) != old);
+
+	return 1;
 }
 
 int nf_connlabels_replace(struct nf_conn *ct,
@@ -32,6 +36,7 @@ int nf_connlabels_replace(struct nf_conn *ct,
 {
 	struct nf_conn_labels *labels;
 	unsigned int size, i;
+	int changed = 0;
 	u32 *dst;
 
 	labels = nf_ct_labels_find(ct);
@@ -43,16 +48,15 @@ int nf_connlabels_replace(struct nf_conn *ct,
 		words32 = size / sizeof(u32);
 
 	dst = (u32 *) labels->bits;
-	if (words32) {
-		for (i = 0; i < words32; i++)
-			replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]);
-	}
+	for (i = 0; i < words32; i++)
+		changed |= replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]);
 
 	size /= sizeof(u32);
 	for (i = words32; i < size; i++) /* pad */
 		replace_u32(&dst[i], 0, 0);
 
-	nf_conntrack_event_cache(IPCT_LABEL, ct);
+	if (changed)
+		nf_conntrack_event_cache(IPCT_LABEL, ct);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(nf_connlabels_replace);
-- 
2.4.10


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH nf-next 3/3] netfilter: nftables: add connlabel set support
  2015-12-07 12:05 [PATCH nf-next 0/3] netfilter: nftables: add set support for conntrack labels Florian Westphal
  2015-12-07 12:05 ` [PATCH nf-next 1/3] netfilter: connlabels: move helpers to xt_connlabel Florian Westphal
  2015-12-07 12:05 ` [PATCH nf-next 2/3] netfilter: labels: don't emit ct event if labels are unchanged Florian Westphal
@ 2015-12-07 12:05 ` Florian Westphal
  2 siblings, 0 replies; 4+ messages in thread
From: Florian Westphal @ 2015-12-07 12:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Conntrack labels are currently sized depending on the iptables
ruleset, i.e. if we're asked to test or set bits 1, 2, and 65 then we
would allocate enough room to store at least bit 65.

However, with nft, the input is just a register with arbitrary runtime
content.

We therefore ask for the upper ceiling we currently have, which is
enough room to store 128 bits.

Alternatively, we could alter nf_connlabel_replace to increase
net->ct.label_words at run time, but since 128 bits is not that
big we'd only save sizeof(long) so it doesn't seem worth it for now.

Caveats: to set a label one has to use:

ct label set ct label | bar

as 'ct label set bar' will clear all other labels.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_ct.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index 8cbca34..5b7fbf9 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -174,6 +174,12 @@ static void nft_ct_set_eval(const struct nft_expr *expr,
 		}
 		break;
 #endif
+#ifdef CONFIG_NF_CONNTRACK_LABELS
+	case NFT_CT_LABELS:
+		nf_connlabels_replace(ct, &regs->data[priv->sreg], NULL,
+				      NF_CT_LABELS_MAX_SIZE / sizeof(u32));
+		break;
+#endif
 	default:
 		break;
 	}
@@ -252,6 +258,9 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
 		if (tb[NFTA_CT_DIRECTION] != NULL)
 			return -EINVAL;
 		len = NF_CT_LABELS_MAX_SIZE;
+		err = nf_connlabels_get(ctx->net, (len * BITS_PER_BYTE) - 1);
+		if (err)
+			return err;
 		break;
 #endif
 	case NFT_CT_HELPER:
@@ -331,9 +340,21 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
 	switch (priv->key) {
 #ifdef CONFIG_NF_CONNTRACK_MARK
 	case NFT_CT_MARK:
+		if (tb[NFTA_CT_DIRECTION])
+			return -EINVAL;
 		len = FIELD_SIZEOF(struct nf_conn, mark);
 		break;
 #endif
+#ifdef CONFIG_NF_CONNTRACK_LABELS
+	case NFT_CT_LABELS:
+		if (tb[NFTA_CT_DIRECTION])
+			return -EINVAL;
+		len = NF_CT_LABELS_MAX_SIZE;
+		err = nf_connlabels_get(ctx->net, (len * BITS_PER_BYTE) - 1);
+		if (err)
+			return err;
+		break;
+#endif
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -353,6 +374,16 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
 static void nft_ct_destroy(const struct nft_ctx *ctx,
 			   const struct nft_expr *expr)
 {
+	struct nft_ct *priv = nft_expr_priv(expr);
+
+	switch (priv->key) {
+#ifdef CONFIG_NF_CONNTRACK_LABELS
+	case NFT_CT_LABELS:
+		nf_connlabels_put(ctx->net);
+		break;
+#endif
+	}
+
 	nft_ct_l3proto_module_put(ctx->afi->family);
 }
 
-- 
2.4.10


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-12-07 12:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-12-07 12:05 [PATCH nf-next 0/3] netfilter: nftables: add set support for conntrack labels Florian Westphal
2015-12-07 12:05 ` [PATCH nf-next 1/3] netfilter: connlabels: move helpers to xt_connlabel Florian Westphal
2015-12-07 12:05 ` [PATCH nf-next 2/3] netfilter: labels: don't emit ct event if labels are unchanged Florian Westphal
2015-12-07 12:05 ` [PATCH nf-next 3/3] netfilter: nftables: add connlabel set support Florian Westphal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).