All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Stéphane Veyret" <sveyret@gmail.com>
To: netfilter-devel@vger.kernel.org
Cc: "Stéphane Veyret" <sveyret@gmail.com>
Subject: [PATCH libnftnl,v3 1/2] src: add ct expectation support
Date: Fri, 17 May 2019 18:40:30 +0200	[thread overview]
Message-ID: <20190517164031.8536-3-sveyret@gmail.com> (raw)
In-Reply-To: <20190517164031.8536-1-sveyret@gmail.com>

Add support for ct expectation objects, used to define specific expectations.

Signed-off-by: Stéphane Veyret <sveyret@gmail.com>
---
 include/libnftnl/object.h           |   7 +
 include/linux/netfilter/nf_tables.h |  13 +-
 include/obj.h                       |   7 +
 src/Makefile.am                     |   1 +
 src/obj/ct_expect.c                 | 193 ++++++++++++++++++++++++++++
 src/object.c                        |   1 +
 6 files changed, 221 insertions(+), 1 deletion(-)
 create mode 100644 src/obj/ct_expect.c

diff --git a/include/libnftnl/object.h b/include/libnftnl/object.h
index 4ce2230..dcb631c 100644
--- a/include/libnftnl/object.h
+++ b/include/libnftnl/object.h
@@ -70,6 +70,13 @@ enum {
 	NFTNL_OBJ_CT_TIMEOUT_ARRAY,
 };
 
+enum {
+	NFTNL_OBJ_CT_EXPECT_L3PROTO = NFTNL_OBJ_BASE,
+	NFTNL_OBJ_CT_EXPECT_L4PROTO,
+	NFTNL_OBJ_CT_EXPECT_DPORT,
+	NFTNL_OBJ_CT_EXPECT_TIMEOUT,
+};
+
 enum {
 	NFTNL_OBJ_LIMIT_RATE	= NFTNL_OBJ_BASE,
 	NFTNL_OBJ_LIMIT_UNIT,
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index fd38cdc..59969f1 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1429,6 +1429,16 @@ enum nft_ct_timeout_attributes {
 };
 #define NFTA_CT_TIMEOUT_MAX	(__NFTA_CT_TIMEOUT_MAX - 1)
 
+enum nft_ct_expectation_attributes {
+	NFTA_CT_EXPECT_UNSPEC,
+	NFTA_CT_EXPECT_L3PROTO,
+	NFTA_CT_EXPECT_L4PROTO,
+	NFTA_CT_EXPECT_DPORT,
+	NFTA_CT_EXPECT_TIMEOUT,
+	__NFTA_CT_EXPECT_MAX,
+};
+#define NFTA_CT_EXPECT_MAX	(__NFTA_CT_EXPECT_MAX - 1)
+
 #define NFT_OBJECT_UNSPEC	0
 #define NFT_OBJECT_COUNTER	1
 #define NFT_OBJECT_QUOTA	2
@@ -1438,7 +1448,8 @@ enum nft_ct_timeout_attributes {
 #define NFT_OBJECT_TUNNEL	6
 #define NFT_OBJECT_CT_TIMEOUT	7
 #define NFT_OBJECT_SECMARK	8
-#define __NFT_OBJECT_MAX	9
+#define NFT_OBJECT_CT_EXPECT	9
+#define __NFT_OBJECT_MAX	10
 #define NFT_OBJECT_MAX		(__NFT_OBJECT_MAX - 1)
 
 /**
diff --git a/include/obj.h b/include/obj.h
index 35b5c40..f5935ab 100644
--- a/include/obj.h
+++ b/include/obj.h
@@ -42,6 +42,12 @@ struct nftnl_obj {
 			uint8_t 	l4proto;
 			uint32_t	timeout[NFTNL_CTTIMEOUT_ARRAY_MAX];
 		} ct_timeout;
+		struct nftnl_obj_ct_expect {
+			uint16_t	l3proto;
+			uint8_t		l4proto;
+			uint16_t	dport;
+			uint32_t	timeout;
+		} ct_expect;
 		struct nftnl_obj_limit {
 			uint64_t	rate;
 			uint64_t	unit;
@@ -99,6 +105,7 @@ extern struct obj_ops obj_ops_counter;
 extern struct obj_ops obj_ops_quota;
 extern struct obj_ops obj_ops_ct_helper;
 extern struct obj_ops obj_ops_ct_timeout;
+extern struct obj_ops obj_ops_ct_expect;
 extern struct obj_ops obj_ops_limit;
 extern struct obj_ops obj_ops_tunnel;
 extern struct obj_ops obj_ops_secmark;
diff --git a/src/Makefile.am b/src/Makefile.am
index 2d5873f..8f9c022 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -65,4 +65,5 @@ libnftnl_la_SOURCES = utils.c		\
 		      obj/limit.c	\
 		      obj/ct_timeout.c 	\
 		      obj/secmark.c	\
+		      obj/ct_expect.c 	\
 		      libnftnl.map
diff --git a/src/obj/ct_expect.c b/src/obj/ct_expect.c
new file mode 100644
index 0000000..16066c4
--- /dev/null
+++ b/src/obj/ct_expect.c
@@ -0,0 +1,193 @@
+/*
+ * (C) 2019 by Stéphane Veyret <sveyret@gmail.com>
+ *
+ * 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 <arpa/inet.h>
+#include <errno.h>
+
+#include <libmnl/libmnl.h>
+
+#include "obj.h"
+
+static int nftnl_obj_ct_expect_set(struct nftnl_obj *e, uint16_t type,
+				   const void *data, uint32_t data_len)
+{
+	struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
+
+	switch (type) {
+	case NFTNL_OBJ_CT_EXPECT_L3PROTO:
+		memcpy(&exp->l3proto, data, sizeof(exp->l3proto));
+		break;
+	case NFTNL_OBJ_CT_EXPECT_L4PROTO:
+		memcpy(&exp->l4proto, data, sizeof(exp->l4proto));
+		break;
+	case NFTNL_OBJ_CT_EXPECT_DPORT:
+		memcpy(&exp->dport, data, sizeof(exp->dport));
+		break;
+	case NFTNL_OBJ_CT_EXPECT_TIMEOUT:
+		memcpy(&exp->timeout, data, sizeof(exp->timeout));
+		break;
+	default:
+		return -1;
+	}
+	return 0;
+}
+
+static const void *nftnl_obj_ct_expect_get(const struct nftnl_obj *e,
+					   uint16_t type, uint32_t *data_len)
+{
+	struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
+
+	switch (type) {
+	case NFTNL_OBJ_CT_EXPECT_L3PROTO:
+		*data_len = sizeof(exp->l3proto);
+		return &exp->l3proto;
+	case NFTNL_OBJ_CT_EXPECT_L4PROTO:
+		*data_len = sizeof(exp->l4proto);
+		return &exp->l4proto;
+	case NFTNL_OBJ_CT_EXPECT_DPORT:
+		*data_len = sizeof(exp->dport);
+		return &exp->dport;
+	case NFTNL_OBJ_CT_EXPECT_TIMEOUT:
+		*data_len = sizeof(exp->timeout);
+		return &exp->timeout;
+	}
+	return NULL;
+}
+
+static int nftnl_obj_ct_expect_cb(const struct nlattr *attr, void *data)
+{
+	int type = mnl_attr_get_type(attr);
+	const struct nlattr **tb = data;
+
+	if (mnl_attr_type_valid(attr, NFTA_CT_EXPECT_MAX) < 0)
+		return MNL_CB_OK;
+
+	switch (type) {
+	case NFTA_CT_EXPECT_L3PROTO:
+		if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
+			abi_breakage();
+		break;
+	case NFTA_CT_EXPECT_L4PROTO:
+		if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
+			abi_breakage();
+		break;
+	case NFTA_CT_EXPECT_DPORT:
+		if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
+			abi_breakage();
+		break;
+	case NFTA_CT_EXPECT_TIMEOUT:
+		if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+			abi_breakage();
+		break;
+	}
+
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static void
+nftnl_obj_ct_expect_build(struct nlmsghdr *nlh, const struct nftnl_obj *e)
+{
+	struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
+
+	if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO))
+		mnl_attr_put_u16(nlh, NFTA_CT_EXPECT_L3PROTO, htons(exp->l3proto));
+	if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO))
+		mnl_attr_put_u8(nlh, NFTA_CT_EXPECT_L4PROTO, exp->l4proto);
+	if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_DPORT))
+		mnl_attr_put_u16(nlh, NFTA_CT_EXPECT_DPORT, htons(exp->dport));
+	if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT))
+		mnl_attr_put_u32(nlh, NFTA_CT_EXPECT_TIMEOUT, exp->timeout);
+}
+
+static int
+nftnl_obj_ct_expect_parse(struct nftnl_obj *e, struct nlattr *attr)
+{
+	struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
+	struct nlattr *tb[NFTA_CT_EXPECT_MAX + 1] = {};
+
+	if (mnl_attr_parse_nested(attr, nftnl_obj_ct_expect_cb, tb) < 0)
+		return -1;
+
+	if (tb[NFTA_CT_EXPECT_L3PROTO]) {
+		exp->l3proto = ntohs(mnl_attr_get_u16(tb[NFTA_CT_EXPECT_L3PROTO]));
+		e->flags |= (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO);
+	}
+	if (tb[NFTA_CT_EXPECT_L4PROTO]) {
+		exp->l4proto = mnl_attr_get_u8(tb[NFTA_CT_EXPECT_L4PROTO]);
+		e->flags |= (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO);
+	}
+	if (tb[NFTA_CT_EXPECT_DPORT]) {
+		exp->dport = ntohs(mnl_attr_get_u16(tb[NFTA_CT_EXPECT_DPORT]));
+		e->flags |= (1 << NFTNL_OBJ_CT_EXPECT_DPORT);
+	}
+	if (tb[NFTA_CT_EXPECT_TIMEOUT]) {
+		exp->timeout = mnl_attr_get_u32(tb[NFTA_CT_EXPECT_TIMEOUT]);
+		e->flags |= (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT);
+	}
+
+	return 0;
+}
+
+static int nftnl_obj_ct_expect_snprintf_default(char *buf, size_t len,
+					       const struct nftnl_obj *e)
+{
+	int ret = 0;
+	int offset = 0, remain = len;
+	struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
+
+	if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO)) {
+		ret = snprintf(buf + offset, len, "family %d ", exp->l3proto);
+		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+	}
+	if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO)) {
+		ret = snprintf(buf + offset, len, "protocol %d ", exp->l4proto);
+		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+	}
+	if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_DPORT)) {
+		ret = snprintf(buf + offset, len, "dport %d ", exp->dport);
+		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+	}
+	if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT)) {
+		ret = snprintf(buf + offset, len, "timeout %d ", exp->timeout);
+		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+	}
+
+	buf[offset] = '\0';
+	return offset;
+}
+
+static int nftnl_obj_ct_expect_snprintf(char *buf, size_t len, uint32_t type,
+				       uint32_t flags,
+				       const struct nftnl_obj *e)
+{
+	if (len)
+		buf[0] = '\0';
+
+	switch (type) {
+	case NFTNL_OUTPUT_DEFAULT:
+		return nftnl_obj_ct_expect_snprintf_default(buf, len, e);
+	case NFTNL_OUTPUT_JSON:
+	default:
+		break;
+	}
+	return -1;
+}
+
+struct obj_ops obj_ops_ct_expect = {
+	.name		= "ct_expect",
+	.type		= NFT_OBJECT_CT_EXPECT,
+	.alloc_len	= sizeof(struct nftnl_obj_ct_expect),
+	.max_attr	= NFTA_CT_EXPECT_MAX,
+	.set		= nftnl_obj_ct_expect_set,
+	.get		= nftnl_obj_ct_expect_get,
+	.parse		= nftnl_obj_ct_expect_parse,
+	.build		= nftnl_obj_ct_expect_build,
+	.snprintf	= nftnl_obj_ct_expect_snprintf,
+};
diff --git a/src/object.c b/src/object.c
index 5c8d183..23f8840 100644
--- a/src/object.c
+++ b/src/object.c
@@ -33,6 +33,7 @@ static struct obj_ops *obj_ops[__NFT_OBJECT_MAX] = {
 	[NFT_OBJECT_TUNNEL]	= &obj_ops_tunnel,
 	[NFT_OBJECT_CT_TIMEOUT] = &obj_ops_ct_timeout,
 	[NFT_OBJECT_SECMARK]	= &obj_ops_secmark,
+	[NFT_OBJECT_CT_EXPECT] = &obj_ops_ct_expect,
 };
 
 static struct obj_ops *nftnl_obj_ops_lookup(uint32_t type)
-- 
2.21.0


  parent reply	other threads:[~2019-05-17 16:43 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-17 16:40 [PATCH nftables,v3] add ct expectations support Stéphane Veyret
2019-05-17 16:40 ` [PATCH nf-next,v3] netfilter: nft_ct: " Stéphane Veyret
2019-05-22  8:46   ` Pablo Neira Ayuso
2019-05-22 11:39     ` Stéphane Veyret
2019-05-22 21:52       ` Pablo Neira Ayuso
2019-05-17 16:40 ` Stéphane Veyret [this message]
2019-05-17 16:40 ` [PATCH libnftnl,v3 2/2] examples: add ct expectation examples Stéphane Veyret

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190517164031.8536-3-sveyret@gmail.com \
    --to=sveyret@gmail.com \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.