All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] nftables: add ct helper set support
@ 2017-02-27 15:02 Florian Westphal
  2017-02-27 15:02 ` [PATCH libnftnl 1/7] object: extend set/get api for u8/u16 types Florian Westphal
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Florian Westphal @ 2017-02-27 15:02 UTC (permalink / raw)
  To: netfilter-devel

This series adds initial support to set conntrack helpers via
the nft objref infrastructure.

As -next is closed I will not push this yet since kernel support
is still missing.

Currently only supported attributes are:

type (e.g. "ftp", "sip)
protocol (udp or tcp)
l3proto (ip, ip6).

l3proto is optional, the kernel will infer it from
the family, i.e. in "inet" case kernel will check for both ipv4 and ipv6.

Let me know in case you spot any isses, patches #3 and #5 could already
be pushed to nft master since they are just preparation patches.


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

* [PATCH libnftnl 1/7] object: extend set/get api for u8/u16 types
  2017-02-27 15:02 [PATCH 0/7] nftables: add ct helper set support Florian Westphal
@ 2017-02-27 15:02 ` Florian Westphal
  2017-02-27 15:02 ` [PATCH libnftnl 2/7] src: ct helper support Florian Westphal
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2017-02-27 15:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/libnftnl/object.h |  4 ++++
 src/libnftnl.map          |  8 ++++++++
 src/object.c              | 26 ++++++++++++++++++++++++++
 3 files changed, 38 insertions(+)

diff --git a/include/libnftnl/object.h b/include/libnftnl/object.h
index 074a37789734..ca3abeae66cc 100644
--- a/include/libnftnl/object.h
+++ b/include/libnftnl/object.h
@@ -44,12 +44,16 @@ void nftnl_obj_unset(struct nftnl_obj *ne, uint16_t attr);
 void nftnl_obj_set_data(struct nftnl_obj *ne, uint16_t attr, const void *data,
 			uint32_t data_len);
 void nftnl_obj_set(struct nftnl_obj *ne, uint16_t attr, const void *data);
+void nftnl_obj_set_u8(struct nftnl_obj *ne, uint16_t attr, uint8_t val);
+void nftnl_obj_set_u16(struct nftnl_obj *ne, uint16_t attr, uint16_t val);
 void nftnl_obj_set_u32(struct nftnl_obj *ne, uint16_t attr, uint32_t val);
 void nftnl_obj_set_u64(struct nftnl_obj *obj, uint16_t attr, uint64_t val);
 void nftnl_obj_set_str(struct nftnl_obj *ne, uint16_t attr, const char *str);
 const void *nftnl_obj_get_data(struct nftnl_obj *ne, uint16_t attr,
 			       uint32_t *data_len);
 const void *nftnl_obj_get(struct nftnl_obj *ne, uint16_t attr);
+uint8_t nftnl_obj_get_u8(struct nftnl_obj *ne, uint16_t attr);
+uint16_t nftnl_obj_get_u16(struct nftnl_obj *obj, uint16_t attr);
 uint32_t nftnl_obj_get_u32(struct nftnl_obj *ne, uint16_t attr);
 uint64_t nftnl_obj_get_u64(struct nftnl_obj *obj, uint16_t attr);
 const char *nftnl_obj_get_str(struct nftnl_obj *ne, uint16_t attr);
diff --git a/src/libnftnl.map b/src/libnftnl.map
index 4282367db5b8..efe63bce98ee 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -301,3 +301,11 @@ global:
 
 local: *;
 };
+
+LIBNFTNL_5.1 {
+	nftnl_obj_get_u8;
+	nftnl_obj_get_u16;
+
+	nftnl_obj_set_u8;
+	nftnl_obj_set_u16;
+} LIBNFTNL_5;
diff --git a/src/object.c b/src/object.c
index 773eff6a5a18..e635f6a8ff0e 100644
--- a/src/object.c
+++ b/src/object.c
@@ -107,6 +107,18 @@ void nftnl_obj_set(struct nftnl_obj *obj, uint16_t attr, const void *data)
 }
 EXPORT_SYMBOL(nftnl_obj_set);
 
+void nftnl_obj_set_u8(struct nftnl_obj *obj, uint16_t attr, uint8_t val)
+{
+	nftnl_obj_set_data(obj, attr, &val, sizeof(uint8_t));
+}
+EXPORT_SYMBOL(nftnl_obj_set_u8);
+
+void nftnl_obj_set_u16(struct nftnl_obj *obj, uint16_t attr, uint16_t val)
+{
+	nftnl_obj_set_data(obj, attr, &val, sizeof(uint16_t));
+}
+EXPORT_SYMBOL(nftnl_obj_set_u16);
+
 void nftnl_obj_set_u32(struct nftnl_obj *obj, uint16_t attr, uint32_t val)
 {
 	nftnl_obj_set_data(obj, attr, &val, sizeof(uint32_t));
@@ -164,6 +176,20 @@ const void *nftnl_obj_get(struct nftnl_obj *obj, uint16_t attr)
 }
 EXPORT_SYMBOL(nftnl_obj_get);
 
+uint8_t nftnl_obj_get_u8(struct nftnl_obj *obj, uint16_t attr)
+{
+	const void *ret = nftnl_obj_get(obj, attr);
+	return ret == NULL ? 0 : *((uint8_t *)ret);
+}
+EXPORT_SYMBOL(nftnl_obj_get_u8);
+
+uint16_t nftnl_obj_get_u16(struct nftnl_obj *obj, uint16_t attr)
+{
+	const void *ret = nftnl_obj_get(obj, attr);
+	return ret == NULL ? 0 : *((uint16_t *)ret);
+}
+EXPORT_SYMBOL(nftnl_obj_get_u16);
+
 uint32_t nftnl_obj_get_u32(struct nftnl_obj *obj, uint16_t attr)
 {
 	const void *ret = nftnl_obj_get(obj, attr);
-- 
2.10.2


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

* [PATCH libnftnl 2/7] src: ct helper support
  2017-02-27 15:02 [PATCH 0/7] nftables: add ct helper set support Florian Westphal
  2017-02-27 15:02 ` [PATCH libnftnl 1/7] object: extend set/get api for u8/u16 types Florian Westphal
@ 2017-02-27 15:02 ` Florian Westphal
  2017-02-27 15:02 ` [PATCH nft 3/7] netlink: BUG when object type is unknown Florian Westphal
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2017-02-27 15:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

add support for ct helper objects, these are used to assign helpers to
connections, similar to iptables -j CT --set-helper target.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/libnftnl/object.h           |   6 ++
 include/linux/netfilter/nf_tables.h |  12 ++-
 include/obj.h                       |   6 ++
 src/Makefile.am                     |   1 +
 src/obj/ct_helper.c                 | 210 ++++++++++++++++++++++++++++++++++++
 src/object.c                        |   3 +-
 6 files changed, 236 insertions(+), 2 deletions(-)
 create mode 100644 src/obj/ct_helper.c

diff --git a/include/libnftnl/object.h b/include/libnftnl/object.h
index ca3abeae66cc..ccd9d19b9364 100644
--- a/include/libnftnl/object.h
+++ b/include/libnftnl/object.h
@@ -34,6 +34,12 @@ enum {
 	NFTNL_OBJ_QUOTA_FLAGS,
 };
 
+enum {
+	NFTNL_OBJ_CT_HELPER_NAME = NFTNL_OBJ_BASE,
+	NFTNL_OBJ_CT_HELPER_L3PROTO,
+	NFTNL_OBJ_CT_HELPER_L4PROTO,
+};
+
 struct nftnl_obj;
 
 struct nftnl_obj *nftnl_obj_alloc(void);
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 05215d30fe5c..121e79cacc49 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1246,10 +1246,20 @@ enum nft_fib_flags {
 	NFTA_FIB_F_OIF		= 1 << 4,	/* restrict to oif */
 };
 
+enum nft_ct_helper_attributes {
+	NFTA_CT_HELPER_UNSPEC,
+	NFTA_CT_HELPER_NAME,
+	NFTA_CT_HELPER_L3PROTO,
+	NFTA_CT_HELPER_L4PROTO,
+	__NFTA_CT_HELPER_MAX,
+};
+#define NFTA_CT_HELPER_MAX	(__NFTA_CT_HELPER_MAX - 1)
+
 #define NFT_OBJECT_UNSPEC	0
 #define NFT_OBJECT_COUNTER	1
 #define NFT_OBJECT_QUOTA	2
-#define __NFT_OBJECT_MAX	3
+#define NFT_OBJECT_CT_HELPER	3
+#define __NFT_OBJECT_MAX	4
 #define NFT_OBJECT_MAX		(__NFT_OBJECT_MAX - 1)
 
 /**
diff --git a/include/obj.h b/include/obj.h
index edbf023f5cdd..d90919f2d86b 100644
--- a/include/obj.h
+++ b/include/obj.h
@@ -30,6 +30,11 @@ struct nftnl_obj {
 			uint64_t	consumed;
 			uint32_t        flags;
 		} quota;
+		struct nftnl_obj_ct_helper {
+			uint16_t	l3proto;
+			uint8_t		l4proto;
+			char		name[16];
+		} ct_helper;
 	} data;
 };
 
@@ -49,6 +54,7 @@ struct obj_ops {
 
 extern struct obj_ops obj_ops_counter;
 extern struct obj_ops obj_ops_quota;
+extern struct obj_ops obj_ops_ct_helper;
 
 #define nftnl_obj_data(obj) (void *)&obj->data
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 485a8c4acbef..77b67b267672 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,5 +53,6 @@ libnftnl_la_SOURCES = utils.c		\
 		      expr/redir.c	\
 		      expr/hash.c	\
 		      obj/counter.c	\
+		      obj/ct_helper.c	\
 		      obj/quota.c	\
 		      libnftnl.map
diff --git a/src/obj/ct_helper.c b/src/obj/ct_helper.c
new file mode 100644
index 000000000000..d6d3111ecce8
--- /dev/null
+++ b/src/obj/ct_helper.c
@@ -0,0 +1,210 @@
+/*
+ * (C) 2017 Red Hat GmbH
+ * Author: Florian Westphal <fw@strlen.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <linux/netfilter/nf_tables.h>
+
+#include "internal.h"
+#include <libmnl/libmnl.h>
+#include <libnftnl/object.h>
+
+#include "obj.h"
+
+static int nftnl_obj_ct_helper_set(struct nftnl_obj *e, uint16_t type,
+				   const void *data, uint32_t data_len)
+{
+	struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
+
+	switch (type) {
+	case NFTNL_OBJ_CT_HELPER_NAME:
+		snprintf(helper->name, sizeof(helper->name), "%s", (const char *)data);
+		break;
+	case NFTNL_OBJ_CT_HELPER_L3PROTO:
+		helper->l3proto = *((uint16_t *)data);
+		break;
+	case NFTNL_OBJ_CT_HELPER_L4PROTO:
+		helper->l4proto = *((uint8_t *)data);
+		break;
+	default:
+		return -1;
+	}
+	return 0;
+}
+
+static const void *nftnl_obj_ct_helper_get(const struct nftnl_obj *e,
+					   uint16_t type, uint32_t *data_len)
+{
+	struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
+
+	switch (type) {
+	case NFTNL_OBJ_CT_HELPER_NAME:
+		*data_len = strlen(helper->name);
+		return helper->name;
+	case NFTNL_OBJ_CT_HELPER_L3PROTO:
+		*data_len = sizeof(helper->l3proto);
+		return &helper->l3proto;
+	case NFTNL_OBJ_CT_HELPER_L4PROTO:
+		*data_len = sizeof(helper->l4proto);
+		return &helper->l4proto;
+	}
+	return NULL;
+}
+
+static int nftnl_obj_ct_helper_cb(const struct nlattr *attr, void *data)
+{
+	const struct nftnl_obj_ct_helper *helper = NULL;
+	int type = mnl_attr_get_type(attr);
+	const struct nlattr **tb = data;
+
+	if (mnl_attr_type_valid(attr, NFTA_CT_HELPER_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch (type) {
+	case NFTA_CT_HELPER_NAME:
+		if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
+			abi_breakage();
+		if (mnl_attr_get_payload_len(attr) >= sizeof(helper->name))
+			abi_breakage();
+		break;
+	case NFTA_CT_HELPER_L3PROTO:
+		if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
+			abi_breakage();
+		break;
+	case NFTA_CT_HELPER_L4PROTO:
+		if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
+			abi_breakage();
+		break;
+	}
+
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static void
+nftnl_obj_ct_helper_build(struct nlmsghdr *nlh, const struct nftnl_obj *e)
+{
+	struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
+
+	if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_NAME))
+		mnl_attr_put_str(nlh, NFTA_CT_HELPER_NAME, helper->name);
+	if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_L3PROTO))
+		mnl_attr_put_u16(nlh, NFTA_CT_HELPER_L3PROTO, htons(helper->l3proto));
+	if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_L4PROTO))
+		mnl_attr_put_u8(nlh, NFTA_CT_HELPER_L4PROTO, helper->l4proto);
+}
+
+static int
+nftnl_obj_ct_helper_parse(struct nftnl_obj *e, struct nlattr *attr)
+{
+	struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
+	struct nlattr *tb[NFTA_CT_HELPER_MAX + 1] = {};
+
+	if (mnl_attr_parse_nested(attr, nftnl_obj_ct_helper_cb, tb) < 0)
+		return -1;
+
+	if (tb[NFTA_CT_HELPER_NAME]) {
+		snprintf(helper->name, sizeof(helper->name), "%s",
+			 mnl_attr_get_str(tb[NFTA_CT_HELPER_NAME]));
+		e->flags |= (1 << NFTNL_OBJ_CT_HELPER_NAME);
+	}
+	if (tb[NFTA_CT_HELPER_L3PROTO]) {
+		helper->l3proto = ntohs(mnl_attr_get_u16(tb[NFTA_CT_HELPER_L3PROTO]));
+		e->flags |= (1 << NFTNL_OBJ_CT_HELPER_L3PROTO);
+	}
+	if (tb[NFTA_CT_HELPER_L4PROTO]) {
+		helper->l4proto = mnl_attr_get_u8(tb[NFTA_CT_HELPER_L4PROTO]);
+		e->flags |= (1 << NFTNL_OBJ_CT_HELPER_L4PROTO);
+	}
+
+	return 0;
+}
+
+static int
+nftnl_obj_quota_json_parse(struct nftnl_obj *e, json_t *root,
+				 struct nftnl_parse_err *err)
+{
+#ifdef JSON_PARSING
+	uint64_t bytes;
+	uint32_t flags;
+
+	if (nftnl_jansson_parse_val(root, "bytes", NFTNL_TYPE_U64, &bytes,
+				  err) == 0)
+		nftnl_obj_set_u64(e, NFTNL_OBJ_QUOTA_BYTES, bytes);
+	if (nftnl_jansson_parse_val(root, "consumed", NFTNL_TYPE_U64, &bytes,
+				    err) == 0)
+		nftnl_obj_set_u64(e, NFTNL_OBJ_QUOTA_CONSUMED, bytes);
+	if (nftnl_jansson_parse_val(root, "flags", NFTNL_TYPE_U32, &flags,
+				  err) == 0)
+		nftnl_obj_set_u32(e, NFTNL_OBJ_QUOTA_FLAGS, flags);
+
+	return 0;
+#else
+	errno = EOPNOTSUPP;
+	return -1;
+#endif
+}
+
+static int nftnl_obj_ct_helper_export(char *buf, size_t size,
+				   const struct nftnl_obj *e, int type)
+{
+	struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
+	NFTNL_BUF_INIT(b, buf, size);
+
+	if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_NAME))
+		nftnl_buf_str(&b, type, helper->name, NAME);
+	if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_L3PROTO))
+		nftnl_buf_u32(&b, type, helper->l3proto, FAMILY);
+	if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_L4PROTO))
+		nftnl_buf_u32(&b, type, helper->l4proto, "service");
+
+	return nftnl_buf_done(&b);
+}
+
+static int nftnl_obj_ct_helper_snprintf_default(char *buf, size_t len,
+					       const struct nftnl_obj *e)
+{
+	struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
+
+	return snprintf(buf, len, "name %s family %d protocol %d ",
+			helper->name, helper->l3proto, helper->l4proto);
+}
+
+static int nftnl_obj_ct_helper_snprintf(char *buf, size_t len, uint32_t type,
+				       uint32_t flags,
+				       const struct nftnl_obj *e)
+{
+	switch (type) {
+	case NFTNL_OUTPUT_DEFAULT:
+		return nftnl_obj_ct_helper_snprintf_default(buf, len, e);
+	case NFTNL_OUTPUT_JSON:
+		return nftnl_obj_ct_helper_export(buf, len, e, type);
+	default:
+		break;
+	}
+	return -1;
+}
+
+struct obj_ops obj_ops_ct_helper = {
+	.name		= "ct_helper",
+	.type		= NFT_OBJECT_CT_HELPER,
+	.alloc_len	= sizeof(struct nftnl_obj_ct_helper),
+	.max_attr	= NFTA_CT_HELPER_MAX,
+	.set		= nftnl_obj_ct_helper_set,
+	.get		= nftnl_obj_ct_helper_get,
+	.parse		= nftnl_obj_ct_helper_parse,
+	.build		= nftnl_obj_ct_helper_build,
+	.snprintf	= nftnl_obj_ct_helper_snprintf,
+	.json_parse	= nftnl_obj_quota_json_parse,
+};
diff --git a/src/object.c b/src/object.c
index e635f6a8ff0e..e1a5ac4757b6 100644
--- a/src/object.c
+++ b/src/object.c
@@ -28,11 +28,12 @@
 static struct obj_ops *obj_ops[] = {
 	[NFT_OBJECT_COUNTER]	= &obj_ops_counter,
 	[NFT_OBJECT_QUOTA]	= &obj_ops_quota,
+	[NFT_OBJECT_CT_HELPER]	= &obj_ops_ct_helper,
 };
 
 static struct obj_ops *nftnl_obj_ops_lookup(uint32_t type)
 {
-	if (type > NFT_OBJECT_QUOTA)
+	if (type > NFT_OBJECT_CT_HELPER)
 		return NULL;
 
 	return obj_ops[type];
-- 
2.10.2


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

* [PATCH nft 3/7] netlink: BUG when object type is unknown
  2017-02-27 15:02 [PATCH 0/7] nftables: add ct helper set support Florian Westphal
  2017-02-27 15:02 ` [PATCH libnftnl 1/7] object: extend set/get api for u8/u16 types Florian Westphal
  2017-02-27 15:02 ` [PATCH libnftnl 2/7] src: ct helper support Florian Westphal
@ 2017-02-27 15:02 ` Florian Westphal
  2017-02-27 15:02 ` [PATCH nft 4/7] src: add initial ct helper support Florian Westphal
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2017-02-27 15:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

This will only trigger during development when adding new object types to
the parser.

The BUG() gives a clear hint where the serialization code needs to go.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 src/netlink.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/netlink.c b/src/netlink.c
index 1f3398225892..d2ede2a47c5d 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -317,6 +317,9 @@ alloc_nftnl_obj(const struct handle *h, struct obj *obj)
 		nftnl_obj_set_u32(nlo, NFTNL_OBJ_QUOTA_FLAGS,
 				  obj->quota.flags);
 		break;
+	default:
+		BUG("Unknown type %d\n", obj->type);
+		break;
 	}
 	return nlo;
 }
-- 
2.10.2


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

* [PATCH nft 4/7] src: add initial ct helper support
  2017-02-27 15:02 [PATCH 0/7] nftables: add ct helper set support Florian Westphal
                   ` (2 preceding siblings ...)
  2017-02-27 15:02 ` [PATCH nft 3/7] netlink: BUG when object type is unknown Florian Westphal
@ 2017-02-27 15:02 ` Florian Westphal
  2017-02-27 15:02 ` [PATCH nft 5/7] evaluate: refactor CMD_OBJ_QUOTA/COUNTER handling Florian Westphal
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2017-02-27 15:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

This adds initial support for defining conntrack helper objects
which can then be assigned to connections using the objref infrastructure:

table ip filter {
  ct helper ftp-standard {
    type "ftp"
    protocol tcp
  }
  chain y {
	 tcp dport 21 ct helper set "ftp-standard"
  }
}

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/ct.h                        |  1 +
 include/linux/netfilter/nf_tables.h |  3 +-
 include/rule.h                      |  7 ++++
 src/ct.c                            | 10 +++++
 src/netlink.c                       | 16 ++++++++
 src/parser_bison.y                  | 80 ++++++++++++++++++++++++++++++++++++-
 src/rule.c                          | 35 +++++++++++++++-
 src/statement.c                     | 10 ++++-
 8 files changed, 157 insertions(+), 5 deletions(-)

diff --git a/include/ct.h b/include/ct.h
index 03e76e619e23..ae900ee4fb61 100644
--- a/include/ct.h
+++ b/include/ct.h
@@ -31,6 +31,7 @@ extern struct error_record *ct_dir_parse(const struct location *loc,
 					 const char *str, int8_t *dir);
 extern struct error_record *ct_key_parse(const struct location *loc, const char *str,
 					 unsigned int *key);
+extern struct error_record *ct_objtype_parse(const struct location *loc, const char *str, int *type);
 
 extern struct stmt *notrack_stmt_alloc(const struct location *loc);
 
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 05215d30fe5c..9fa2aa49a36c 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1249,7 +1249,8 @@ enum nft_fib_flags {
 #define NFT_OBJECT_UNSPEC	0
 #define NFT_OBJECT_COUNTER	1
 #define NFT_OBJECT_QUOTA	2
-#define __NFT_OBJECT_MAX	3
+#define NFT_OBJECT_CT_HELPER	3
+#define __NFT_OBJECT_MAX	4
 #define NFT_OBJECT_MAX		(__NFT_OBJECT_MAX - 1)
 
 /**
diff --git a/include/rule.h b/include/rule.h
index f5160daf4d8e..6a495a9a36be 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -260,6 +260,12 @@ struct quota {
 	uint32_t	flags;
 };
 
+struct ct {
+	char helper_name[16];
+	uint16_t l3proto;
+	uint8_t l4proto;
+};
+
 /**
  * struct obj - nftables stateful object statement
  *
@@ -277,6 +283,7 @@ struct obj {
 	union {
 		struct counter		counter;
 		struct quota		quota;
+		struct ct		ct;
 	};
 };
 
diff --git a/src/ct.c b/src/ct.c
index 31c7a4b1beda..bd9b25bed1f9 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -346,6 +346,16 @@ struct error_record *ct_key_parse(const struct location *loc, const char *str,
 	return error(loc, "syntax error, unexpected %s, known keys are %s", str, buf);
 }
 
+struct error_record *ct_objtype_parse(const struct location *loc, const char *str, int *type)
+{
+	if (strcmp(str, "helper") == 0) {
+		*type = NFT_OBJECT_CT_HELPER;
+		return NULL;
+	}
+
+	return error(loc, "unknown ct class '%s', want 'helper'", str);
+}
+
 struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key,
 			   int8_t direction)
 {
diff --git a/src/netlink.c b/src/netlink.c
index d2ede2a47c5d..5f2ba107bfd3 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -317,6 +317,15 @@ alloc_nftnl_obj(const struct handle *h, struct obj *obj)
 		nftnl_obj_set_u32(nlo, NFTNL_OBJ_QUOTA_FLAGS,
 				  obj->quota.flags);
 		break;
+	case NFT_OBJECT_CT_HELPER:
+		nftnl_obj_set_str(nlo, NFTNL_OBJ_CT_HELPER_NAME,
+				  obj->ct.helper_name);
+		nftnl_obj_set_u8(nlo, NFTNL_OBJ_CT_HELPER_L4PROTO,
+				  obj->ct.l4proto);
+		if (obj->ct.l3proto)
+			nftnl_obj_set_u16(nlo, NFTNL_OBJ_CT_HELPER_L3PROTO,
+					  obj->ct.l3proto);
+		break;
 	default:
 		BUG("Unknown type %d\n", obj->type);
 		break;
@@ -1812,6 +1821,13 @@ static struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
 			nftnl_obj_get_u64(nlo, NFTNL_OBJ_QUOTA_CONSUMED);
 		obj->quota.flags =
 			nftnl_obj_get_u32(nlo, NFTNL_OBJ_QUOTA_FLAGS);
+		break;
+	case NFT_OBJECT_CT_HELPER:
+		snprintf(obj->ct.helper_name, sizeof(obj->ct.helper_name), "%s",
+			 nftnl_obj_get_str(nlo, NFTNL_OBJ_CT_HELPER_NAME));
+		obj->ct.l3proto = nftnl_obj_get_u16(nlo, NFTNL_OBJ_CT_HELPER_L3PROTO);
+		obj->ct.l4proto = nftnl_obj_get_u8(nlo, NFTNL_OBJ_CT_HELPER_L4PROTO);
+		break;
 	}
 	obj->type = type;
 
diff --git a/src/parser_bison.y b/src/parser_bison.y
index b295bfde2ed3..3ff11ff18cfe 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -136,6 +136,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 	struct obj		*obj;
 	struct counter		*counter;
 	struct quota		*quota;
+	struct ct		*ct;
 	const struct datatype	*datatype;
 	struct handle_spec	handle_spec;
 	struct position_spec	position_spec;
@@ -469,7 +470,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %type <set>			map_block_alloc map_block
 %destructor { set_free($$); }	map_block_alloc
 
-%type <obj>			obj_block_alloc counter_block quota_block
+%type <obj>			obj_block_alloc counter_block quota_block ct_block
 %destructor { obj_free($$); }	obj_block_alloc
 
 %type <list>			stmt_list
@@ -634,6 +635,10 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %destructor { expr_free($$); }	tcp_hdr_expr
 %type <val>			tcp_hdr_field
 
+%type <val>			ct_l4protoname	ct_l3protoname
+%type <string>			ct_obj_kind
+%destructor { xfree($$); }     	ct_obj_kind
+
 %%
 
 input			:	/* empty */
@@ -1160,6 +1165,24 @@ table_block		:	/* empty */	{ $$ = $<table>-1; }
 				list_add_tail(&$4->list, &$1->objs);
 				$$ = $1;
 			}
+			|	table_block	CT	ct_obj_kind	obj_identifier  obj_block_alloc '{'     ct_block     '}' stmt_seperator
+			{
+				struct error_record *erec;
+				int type;
+
+				erec = ct_objtype_parse(&@$, $3, &type);
+				if (erec != NULL) {
+					erec_queue(erec, state->msgs);
+					YYERROR;
+				}
+
+				$5->location = @4;
+				$5->type = type;
+				handle_merge(&$5->handle, &$4);
+				handle_free(&$4);
+				list_add_tail(&$5->list, &$1->objs);
+				$$ = $1;
+			}
 			;
 
 chain_block_alloc	:	/* empty */
@@ -1354,6 +1377,16 @@ quota_block		:	/* empty */	{ $$ = $<obj>-1; }
 			}
 			;
 
+ct_block		:	/* empty */	{ $$ = $<obj>-1; }
+			|       ct_block     common_block
+			|       ct_block     stmt_seperator
+			|       ct_block     ct_config
+			{
+				$$ = $1;
+			}
+			;
+
+
 type_identifier		:	STRING	{ $$ = $1; }
 			|	MARK	{ $$ = xstrdup("mark"); }
 			|	DSCP	{ $$ = xstrdup("dscp"); }
@@ -2546,6 +2579,40 @@ quota_obj		:	quota_config
 			}
 			;
 
+ct_obj_kind		:	STRING		{ $$ = $1; }
+			;
+
+ct_l3protoname		: 	IP		{ $$ = NFPROTO_IPV4; }
+			|	IP6		{ $$ = NFPROTO_IPV6; }
+			;
+
+ct_l4protoname		:	TCP	{ $$ = IPPROTO_TCP; }
+			|	UDP	{ $$ = IPPROTO_UDP; }
+			;
+
+ct_config		:	TYPE	QUOTED_STRING	stmt_seperator
+			{
+				struct ct *ct;
+				int ret;
+
+				ct = &$<obj>0->ct;
+
+				ret = snprintf(ct->helper_name, sizeof(ct->helper_name), "%s", $2);
+				if (ret <= 0 || ret >= (int)sizeof(ct->helper_name)) {
+					erec_queue(error(&@2, "invalid name '%s', max length is %u\n", $2, (int)sizeof(ct->helper_name)), state->msgs);
+					YYERROR;
+				}
+			}
+			|	PROTOCOL	ct_l4protoname	stmt_seperator
+			{
+				$<obj>0->ct.l4proto = $2;
+			}
+			|	L3PROTOCOL	ct_l3protoname	stmt_seperator
+			{
+				$<obj>0->ct.l4proto = $2;
+			}
+			;
+
 relational_expr		:	expr	/* implicit */	rhs_expr
 			{
 				$$ = relational_expr_alloc(&@$, OP_IMPLICIT, $1, $2);
@@ -2988,7 +3055,16 @@ ct_stmt			:	CT	ct_key		SET	expr
 					YYERROR;
 				}
 
-				$$ = ct_stmt_alloc(&@$, key, $4);
+				switch (key) {
+				case NFT_CT_HELPER:
+					$$ = objref_stmt_alloc(&@$);
+					$$->objref.type = NFT_OBJECT_CT_HELPER;
+					$$->objref.expr = $4;
+					break;
+				default:
+					$$ = ct_stmt_alloc(&@$, key, $4);
+					break;
+				}
 			}
 			;
 
diff --git a/src/rule.c b/src/rule.c
index b47076f000ee..eb31f0e9ec5e 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1171,6 +1171,29 @@ struct obj *obj_lookup(const struct table *table, const char *name,
 	return NULL;
 }
 
+static const char *proto_name_proto(uint8_t l4, char *b, size_t l)
+{
+	switch (l4) {
+	case IPPROTO_UDP: return "udp";
+	case IPPROTO_TCP: return "tcp";
+	}
+
+	snprintf(b, l, "%d\n", l4);
+	return b;
+}
+
+static const char *proto_name_family(uint16_t family, char *b, size_t l)
+{
+	switch (family) {
+	case NFPROTO_IPV4: return "ip";
+	case NFPROTO_IPV6: return "ip6";
+	case NFPROTO_INET: return "inet";
+	}
+
+	snprintf(b, l, "%d\n", family);
+	return b;
+}
+
 static void obj_print_data(const struct obj *obj,
 			   struct print_fmt_options *opts)
 {
@@ -1201,6 +1224,15 @@ static void obj_print_data(const struct obj *obj,
 		}
 		}
 		break;
+	case NFT_OBJECT_CT_HELPER: {
+		char buf[16];
+
+		printf("ct helper %s {\n", obj->handle.obj);
+		printf("\t\ttype \"%s\"\n", obj->ct.helper_name);
+		printf("\t\tl3proto %s\n", proto_name_family(obj->ct.l3proto, buf, sizeof(buf)));
+		printf("\t\tprotocol %s", proto_name_proto(obj->ct.l4proto, buf, sizeof(buf)));
+		break;
+		}
 	default:
 		printf("unknown {%s", opts->nl);
 		break;
@@ -1210,11 +1242,12 @@ static void obj_print_data(const struct obj *obj,
 static const char *obj_type_name_array[] = {
 	[NFT_OBJECT_COUNTER]	= "counter",
 	[NFT_OBJECT_QUOTA]	= "quota",
+	[NFT_OBJECT_CT_HELPER]	= "",
 };
 
 const char *obj_type_name(enum stmt_types type)
 {
-	assert(type <= NFT_OBJECT_QUOTA && obj_type_name_array[type]);
+	assert(type <= NFT_OBJECT_CT_HELPER && obj_type_name_array[type]);
 
 	return obj_type_name_array[type];
 }
diff --git a/src/statement.c b/src/statement.c
index 7ffd25f98ea6..d824dc0bd91a 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -174,6 +174,7 @@ struct stmt *counter_stmt_alloc(const struct location *loc)
 static const char *objref_type[NFT_OBJECT_MAX + 1] = {
 	[NFT_OBJECT_COUNTER]	= "counter",
 	[NFT_OBJECT_QUOTA]	= "quota",
+	[NFT_OBJECT_CT_HELPER]	= "cthelper",
 };
 
 static const char *objref_type_name(uint32_t type)
@@ -186,7 +187,14 @@ static const char *objref_type_name(uint32_t type)
 
 static void objref_stmt_print(const struct stmt *stmt)
 {
-	printf("%s name ", objref_type_name(stmt->objref.type));
+	switch (stmt->objref.type) {
+	case NFT_OBJECT_CT_HELPER:
+		printf("ct helper set ");
+		break;
+	default:
+		printf("%s name ", objref_type_name(stmt->objref.type));
+		break;
+	}
 	expr_print(stmt->objref.expr);
 }
 
-- 
2.10.2


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

* [PATCH nft 5/7] evaluate: refactor CMD_OBJ_QUOTA/COUNTER handling
  2017-02-27 15:02 [PATCH 0/7] nftables: add ct helper set support Florian Westphal
                   ` (3 preceding siblings ...)
  2017-02-27 15:02 ` [PATCH nft 4/7] src: add initial ct helper support Florian Westphal
@ 2017-02-27 15:02 ` Florian Westphal
  2017-02-27 15:02 ` [PATCH nft 6/7] src: allow listing all ct helpers Florian Westphal
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2017-02-27 15:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

... to make adding CMD_OBJ_CT_HELPER support easier.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 src/evaluate.c | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index 87da2fd83597..4ac55e177d54 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2916,12 +2916,29 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
 	}
 }
 
+static int cmd_evaluate_list_obj(struct eval_ctx *ctx, const struct cmd *cmd,
+				 uint32_t obj_type)
+{
+	const struct table *table;
+
+	if (obj_type == NFT_OBJECT_UNSPEC)
+		obj_type = NFT_OBJECT_COUNTER;
+
+	table = table_lookup(&cmd->handle);
+	if (table == NULL)
+		return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
+				 cmd->handle.table);
+	if (obj_lookup(table, cmd->handle.obj, obj_type) == NULL)
+		return cmd_error(ctx, "Could not process rule: Object '%s' does not exist",
+					 cmd->handle.obj);
+	return 0;
+}
+
 static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 {
 	struct table *table;
 	struct set *set;
 	int ret;
-	uint32_t obj_type = NFT_OBJECT_UNSPEC;
 
 	ret = cache_update(cmd->op, ctx->msgs);
 	if (ret < 0)
@@ -2977,18 +2994,9 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 					 cmd->handle.chain);
 		return 0;
 	case CMD_OBJ_QUOTA:
-		obj_type = NFT_OBJECT_QUOTA;
+		return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_QUOTA);
 	case CMD_OBJ_COUNTER:
-		if (obj_type == NFT_OBJECT_UNSPEC)
-			obj_type = NFT_OBJECT_COUNTER;
-		table = table_lookup(&cmd->handle);
-		if (table == NULL)
-			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
-		if (obj_lookup(table, cmd->handle.obj, obj_type) == NULL)
-			return cmd_error(ctx, "Could not process rule: Object '%s' does not exist",
-					 cmd->handle.obj);
-		return 0;
+		return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_COUNTER);
 	case CMD_OBJ_COUNTERS:
 	case CMD_OBJ_QUOTAS:
 		if (cmd->handle.table == NULL)
-- 
2.10.2


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

* [PATCH nft 6/7] src: allow listing all ct helpers
  2017-02-27 15:02 [PATCH 0/7] nftables: add ct helper set support Florian Westphal
                   ` (4 preceding siblings ...)
  2017-02-27 15:02 ` [PATCH nft 5/7] evaluate: refactor CMD_OBJ_QUOTA/COUNTER handling Florian Westphal
@ 2017-02-27 15:02 ` Florian Westphal
  2017-02-27 15:02 ` [PATCH nft 7/7] src: implement add/create/delete for ct helper objects Florian Westphal
  2017-02-28 11:30 ` [PATCH 0/7] nftables: add ct helper set support Pablo Neira Ayuso
  7 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2017-02-27 15:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

this implements
nft list ct helpers table filter
table ip filter {
    ct helper ftp-standard {
..

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/rule.h     |  1 +
 src/evaluate.c     |  1 +
 src/parser_bison.y | 19 +++++++++++++++++++
 src/rule.c         |  2 ++
 4 files changed, 23 insertions(+)

diff --git a/include/rule.h b/include/rule.h
index 6a495a9a36be..882fc3350c6c 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -370,6 +370,7 @@ enum cmd_obj {
 	CMD_OBJ_COUNTERS,
 	CMD_OBJ_QUOTA,
 	CMD_OBJ_QUOTAS,
+	CMD_OBJ_CT_HELPERS,
 };
 
 struct export {
diff --git a/src/evaluate.c b/src/evaluate.c
index 4ac55e177d54..4c8c1e8a4229 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2999,6 +2999,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 		return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_COUNTER);
 	case CMD_OBJ_COUNTERS:
 	case CMD_OBJ_QUOTAS:
+	case CMD_OBJ_CT_HELPERS:
 		if (cmd->handle.table == NULL)
 			return 0;
 		if (table_lookup(&cmd->handle) == NULL)
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 3ff11ff18cfe..076e59ae603d 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -985,6 +985,25 @@ list_cmd		:	TABLE		table_spec
 			{
 				$$ = cmd_alloc(CMD_LIST, CMD_OBJ_MAP, &$2, &@$, NULL);
 			}
+			|       CT              STRING  TABLE   table_spec
+			{
+				int cmd;
+
+				if (strcmp($2, "helpers") == 0) {
+					cmd = CMD_OBJ_CT_HELPERS;
+				} else {
+					struct error_record *erec;
+
+					erec = error(&@$, "unknown ct class '%s', want 'helpers'", $2);
+
+					if (erec != NULL) {
+						erec_queue(erec, state->msgs);
+						YYERROR;
+					}
+				}
+
+				$$ = cmd_alloc(CMD_LIST, cmd, &$4, &@$, NULL);
+			}
 			;
 
 reset_cmd		:	COUNTERS	ruleset_spec
diff --git a/src/rule.c b/src/rule.c
index eb31f0e9ec5e..889aa719afaa 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1468,6 +1468,8 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_QUOTA:
 	case CMD_OBJ_QUOTAS:
 		return do_list_obj(ctx, cmd, NFT_OBJECT_QUOTA);
+	case CMD_OBJ_CT_HELPERS:
+		return do_list_obj(ctx, cmd, NFT_OBJECT_CT_HELPER);
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
 	}
-- 
2.10.2


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

* [PATCH nft 7/7] src: implement add/create/delete for ct helper objects
  2017-02-27 15:02 [PATCH 0/7] nftables: add ct helper set support Florian Westphal
                   ` (5 preceding siblings ...)
  2017-02-27 15:02 ` [PATCH nft 6/7] src: allow listing all ct helpers Florian Westphal
@ 2017-02-27 15:02 ` Florian Westphal
  2017-02-28 11:30 ` [PATCH 0/7] nftables: add ct helper set support Pablo Neira Ayuso
  7 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2017-02-27 15:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/rule.h     |  4 ++++
 src/evaluate.c     |  4 ++++
 src/parser_bison.y | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/rule.c         | 22 +++++++++++++++++++
 4 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index 882fc3350c6c..3edf7b9f36bb 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -370,6 +370,7 @@ enum cmd_obj {
 	CMD_OBJ_COUNTERS,
 	CMD_OBJ_QUOTA,
 	CMD_OBJ_QUOTAS,
+	CMD_OBJ_CT_HELPER,
 	CMD_OBJ_CT_HELPERS,
 };
 
@@ -438,6 +439,9 @@ struct cmd {
 extern struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
 			     const struct handle *h, const struct location *loc,
 			     void *data);
+extern struct cmd *cmd_alloc_obj_ct(enum cmd_ops op, int type,
+				    const struct handle *h,
+				    const struct location *loc, void *data);
 extern void cmd_free(struct cmd *cmd);
 
 #include <payload.h>
diff --git a/src/evaluate.c b/src/evaluate.c
index 4c8c1e8a4229..2f943c238e6f 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2887,6 +2887,7 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd)
 		return table_evaluate(ctx, cmd->table);
 	case CMD_OBJ_COUNTER:
 	case CMD_OBJ_QUOTA:
+	case CMD_OBJ_CT_HELPER:
 		return 0;
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
@@ -2910,6 +2911,7 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_TABLE:
 	case CMD_OBJ_COUNTER:
 	case CMD_OBJ_QUOTA:
+	case CMD_OBJ_CT_HELPER:
 		return 0;
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
@@ -2997,6 +2999,8 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 		return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_QUOTA);
 	case CMD_OBJ_COUNTER:
 		return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_COUNTER);
+	case CMD_OBJ_CT_HELPER:
+		return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_CT_HELPER);
 	case CMD_OBJ_COUNTERS:
 	case CMD_OBJ_QUOTAS:
 	case CMD_OBJ_CT_HELPERS:
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 076e59ae603d..22d922784f19 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -558,8 +558,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %type <expr>			and_rhs_expr exclusive_or_rhs_expr inclusive_or_rhs_expr
 %destructor { expr_free($$); }	and_rhs_expr exclusive_or_rhs_expr inclusive_or_rhs_expr
 
-%type <obj>			counter_obj quota_obj
-%destructor { obj_free($$); }	counter_obj quota_obj
+%type <obj>			counter_obj quota_obj ct_obj_alloc
+%destructor { obj_free($$); }	counter_obj quota_obj ct_obj_alloc
 
 %type <expr>			relational_expr
 %destructor { expr_free($$); }	relational_expr
@@ -809,6 +809,19 @@ add_cmd			:	TABLE		table_spec
 			{
 				$$ = cmd_alloc(CMD_ADD, CMD_OBJ_QUOTA, &$2, &@$, $3);
 			}
+			|	CT	STRING	obj_spec	ct_obj_alloc	'{' ct_block '}'	stmt_seperator
+			{
+				struct error_record *erec;
+				int type;
+
+				erec = ct_objtype_parse(&@$, $2, &type);
+				if (erec != NULL) {
+					erec_queue(erec, state->msgs);
+					YYERROR;
+				}
+
+				$$ = cmd_alloc_obj_ct(CMD_ADD, type, &$3, &@$, $4);
+			}
 			;
 
 replace_cmd		:	RULE		ruleid_spec	rule
@@ -875,6 +888,19 @@ create_cmd		:	TABLE		table_spec
 			{
 				$$ = cmd_alloc(CMD_CREATE, CMD_OBJ_QUOTA, &$2, &@$, $3);
 			}
+			|	CT	STRING	obj_spec	ct_obj_alloc	'{' ct_block '}'	stmt_seperator
+			{
+				struct error_record *erec;
+				int type;
+
+				erec = ct_objtype_parse(&@$, $2, &type);
+				if (erec != NULL) {
+					erec_queue(erec, state->msgs);
+					YYERROR;
+				}
+
+				$$ = cmd_alloc_obj_ct(CMD_CREATE, type, &$3, &@$, $4);
+			}
 			;
 
 insert_cmd		:	RULE		rule_position	rule
@@ -915,6 +941,19 @@ delete_cmd		:	TABLE		table_spec
 			{
 				$$ = cmd_alloc(CMD_DELETE, CMD_OBJ_QUOTA, &$2, &@$, NULL);
 			}
+			|	CT	STRING	obj_spec	ct_obj_alloc
+			{
+				struct error_record *erec;
+				int type;
+
+				erec = ct_objtype_parse(&@$, $2, &type);
+				if (erec != NULL) {
+					erec_queue(erec, state->msgs);
+					YYERROR;
+				}
+
+				$$ = cmd_alloc_obj_ct(CMD_DELETE, type, &$3, &@$, $4);
+			}
 			;
 
 list_cmd		:	TABLE		table_spec
@@ -985,6 +1024,19 @@ list_cmd		:	TABLE		table_spec
 			{
 				$$ = cmd_alloc(CMD_LIST, CMD_OBJ_MAP, &$2, &@$, NULL);
 			}
+			|	CT		STRING	obj_spec
+			{
+				struct error_record *erec;
+				int type;
+
+				erec = ct_objtype_parse(&@$, $2, &type);
+				if (erec != NULL) {
+					erec_queue(erec, state->msgs);
+					YYERROR;
+				}
+
+				$$ = cmd_alloc_obj_ct(CMD_LIST, type, &$3, &@$, NULL);
+			}
 			|       CT              STRING  TABLE   table_spec
 			{
 				int cmd;
@@ -2632,6 +2684,13 @@ ct_config		:	TYPE	QUOTED_STRING	stmt_seperator
 			}
 			;
 
+ct_obj_alloc		:
+			{
+				$$ = obj_alloc(&@$);
+				$$->type = NFT_OBJECT_CT_HELPER;
+			}
+			;
+
 relational_expr		:	expr	/* implicit */	rhs_expr
 			{
 				$$ = relational_expr_alloc(&@$, OP_IMPLICIT, $1, $2);
diff --git a/src/rule.c b/src/rule.c
index 889aa719afaa..e412eac362fb 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -883,6 +883,7 @@ void cmd_free(struct cmd *cmd)
 			break;
 		case CMD_OBJ_COUNTER:
 		case CMD_OBJ_QUOTA:
+		case CMD_OBJ_CT_HELPER:
 			obj_free(cmd->object);
 			break;
 		default:
@@ -999,6 +1000,7 @@ static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl)
 		return do_add_setelems(ctx, &cmd->handle, cmd->expr, excl);
 	case CMD_OBJ_COUNTER:
 	case CMD_OBJ_QUOTA:
+	case CMD_OBJ_CT_HELPER:
 		return netlink_add_obj(ctx, &cmd->handle, cmd->object, excl);
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
@@ -1069,6 +1071,9 @@ static int do_command_delete(struct netlink_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_QUOTA:
 		return netlink_delete_obj(ctx, &cmd->handle, &cmd->location,
 					  NFT_OBJECT_QUOTA);
+	case CMD_OBJ_CT_HELPER:
+		return netlink_delete_obj(ctx, &cmd->handle, &cmd->location,
+					  NFT_OBJECT_CT_HELPER);
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
 	}
@@ -1468,6 +1473,7 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_QUOTA:
 	case CMD_OBJ_QUOTAS:
 		return do_list_obj(ctx, cmd, NFT_OBJECT_QUOTA);
+	case CMD_OBJ_CT_HELPER:
 	case CMD_OBJ_CT_HELPERS:
 		return do_list_obj(ctx, cmd, NFT_OBJECT_CT_HELPER);
 	default:
@@ -1616,6 +1622,22 @@ static int do_command_describe(struct netlink_ctx *ctx, struct cmd *cmd)
 	return 0;
 }
 
+struct cmd *cmd_alloc_obj_ct(enum cmd_ops op, int type, const struct handle *h,
+			     const struct location *loc, void *data)
+{
+	enum cmd_obj cmd_obj;
+
+	switch (type) {
+	case NFT_OBJECT_CT_HELPER:
+		cmd_obj = CMD_OBJ_CT_HELPER;
+		break;
+	default:
+		BUG("missing type mapping");
+	}
+
+	return cmd_alloc(op, cmd_obj, h, loc, data);
+}
+
 int do_command(struct netlink_ctx *ctx, struct cmd *cmd)
 {
 	switch (cmd->op) {
-- 
2.10.2


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

* Re: [PATCH 0/7] nftables: add ct helper set support
  2017-02-27 15:02 [PATCH 0/7] nftables: add ct helper set support Florian Westphal
                   ` (6 preceding siblings ...)
  2017-02-27 15:02 ` [PATCH nft 7/7] src: implement add/create/delete for ct helper objects Florian Westphal
@ 2017-02-28 11:30 ` Pablo Neira Ayuso
  7 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2017-02-28 11:30 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel

On Mon, Feb 27, 2017 at 04:02:48PM +0100, Florian Westphal wrote:
> This series adds initial support to set conntrack helpers via
> the nft objref infrastructure.
> 
> As -next is closed I will not push this yet since kernel support
> is still missing.
> 
> Currently only supported attributes are:
> 
> type (e.g. "ftp", "sip)
> protocol (udp or tcp)
> l3proto (ip, ip6).
> 
> l3proto is optional, the kernel will infer it from
> the family, i.e. in "inet" case kernel will check for both ipv4 and ipv6.
> 
> Let me know in case you spot any isses, patches #3 and #5 could already
> be pushed to nft master since they are just preparation patches.

Series looks good, thanks Florian.

Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>

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

end of thread, other threads:[~2017-02-28 11:31 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-27 15:02 [PATCH 0/7] nftables: add ct helper set support Florian Westphal
2017-02-27 15:02 ` [PATCH libnftnl 1/7] object: extend set/get api for u8/u16 types Florian Westphal
2017-02-27 15:02 ` [PATCH libnftnl 2/7] src: ct helper support Florian Westphal
2017-02-27 15:02 ` [PATCH nft 3/7] netlink: BUG when object type is unknown Florian Westphal
2017-02-27 15:02 ` [PATCH nft 4/7] src: add initial ct helper support Florian Westphal
2017-02-27 15:02 ` [PATCH nft 5/7] evaluate: refactor CMD_OBJ_QUOTA/COUNTER handling Florian Westphal
2017-02-27 15:02 ` [PATCH nft 6/7] src: allow listing all ct helpers Florian Westphal
2017-02-27 15:02 ` [PATCH nft 7/7] src: implement add/create/delete for ct helper objects Florian Westphal
2017-02-28 11:30 ` [PATCH 0/7] nftables: add ct helper set support Pablo Neira Ayuso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.