All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4 v2] nf: netfilter: nf_tables_api: Add new attributes into nft_set to store user data.
@ 2016-01-05 13:03 Carlos Falgueras García
  2016-01-05 13:03 ` [PATCH 3/4 v2] libnftnl: set: Implement new buffer of TLV objects Carlos Falgueras García
  0 siblings, 1 reply; 4+ messages in thread
From: Carlos Falgueras García @ 2016-01-05 13:03 UTC (permalink / raw)
  To: netfilter-devel; +Cc: pablo, kaber

User data is stored at after 'nft_set_ops' private data into 'data[]'
flexible array. The field 'udata' points to user data and 'udlen' stores
its length.

Add new flag NFTA_SET_USERDATA.

Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
---
 include/net/netfilter/nf_tables.h        |  4 ++++
 include/uapi/linux/netfilter/nf_tables.h |  2 ++
 net/netfilter/nf_tables_api.c            | 21 ++++++++++++++++++++-
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 4bd7508..ef44df3 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -293,6 +293,8 @@ void nft_unregister_set(struct nft_set_ops *ops);
  * 	@timeout: default timeout value in msecs
  * 	@gc_int: garbage collection interval in msecs
  *	@policy: set parameterization (see enum nft_set_policies)
+ *	@udlen: user data length
+ *	@udata: user data
  * 	@ops: set ops
  * 	@pnet: network namespace
  * 	@flags: set flags
@@ -312,6 +314,8 @@ struct nft_set {
 	u64				timeout;
 	u32				gc_int;
 	u16				policy;
+	u16				udlen;
+	unsigned char			*udata;
 	/* runtime data below here */
 	const struct nft_set_ops	*ops ____cacheline_aligned;
 	possible_net_t			pnet;
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index d8c8a7c..33ac070 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -289,6 +289,7 @@ enum nft_set_desc_attributes {
  * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
  * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
  * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
+ * @NFTA_SET_USERDATA: user data (NLA_BINARY)
  */
 enum nft_set_attributes {
 	NFTA_SET_UNSPEC,
@@ -304,6 +305,7 @@ enum nft_set_attributes {
 	NFTA_SET_ID,
 	NFTA_SET_TIMEOUT,
 	NFTA_SET_GC_INTERVAL,
+	NFTA_SET_USERDATA,
 	__NFTA_SET_MAX
 };
 #define NFTA_SET_MAX		(__NFTA_SET_MAX - 1)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 2cb429d..628b3d2 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2333,6 +2333,8 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
 	[NFTA_SET_ID]			= { .type = NLA_U32 },
 	[NFTA_SET_TIMEOUT]		= { .type = NLA_U64 },
 	[NFTA_SET_GC_INTERVAL]		= { .type = NLA_U32 },
+	[NFTA_SET_USERDATA]		= { .type = NLA_BINARY,
+					    .len  = NFT_USERDATA_MAXLEN },
 };
 
 static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
@@ -2494,6 +2496,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
 			goto nla_put_failure;
 	}
 
+	if (nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
+		goto nla_put_failure;
+
 	desc = nla_nest_start(skb, NFTA_SET_DESC);
 	if (desc == NULL)
 		goto nla_put_failure;
@@ -2704,6 +2709,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
 	u64 timeout;
 	u32 ktype, dtype, flags, policy, gc_int;
 	struct nft_set_desc desc;
+	u16 udlen;
+	unsigned char *udata;
 	int err;
 
 	if (nla[NFTA_SET_TABLE] == NULL ||
@@ -2816,12 +2823,16 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
 	if (IS_ERR(ops))
 		return PTR_ERR(ops);
 
+	udlen = 0;
+	if (nla[NFTA_SET_USERDATA])
+		udlen = nla_len(nla[NFTA_SET_USERDATA]);
+
 	size = 0;
 	if (ops->privsize != NULL)
 		size = ops->privsize(nla);
 
 	err = -ENOMEM;
-	set = kzalloc(sizeof(*set) + size, GFP_KERNEL);
+	set = kzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
 	if (set == NULL)
 		goto err1;
 
@@ -2830,6 +2841,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
 	if (err < 0)
 		goto err2;
 
+	udata = NULL;
+	if (udlen) {
+		udata = set->data + size;
+		nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
+	}
+
 	INIT_LIST_HEAD(&set->bindings);
 	write_pnet(&set->pnet, net);
 	set->ops   = ops;
@@ -2840,6 +2857,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
 	set->flags = flags;
 	set->size  = desc.size;
 	set->policy = policy;
+	set->udlen  = udlen;
+	set->udata  = udata;
 	set->timeout = timeout;
 	set->gc_int = gc_int;
 
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 3/4 v2] libnftnl: set: Implement new buffer of TLV objects.
  2016-01-05 13:03 [PATCH 1/4 v2] nf: netfilter: nf_tables_api: Add new attributes into nft_set to store user data Carlos Falgueras García
@ 2016-01-05 13:03 ` Carlos Falgueras García
  2016-01-05 13:28   ` Florian Westphal
  0 siblings, 1 reply; 4+ messages in thread
From: Carlos Falgueras García @ 2016-01-05 13:03 UTC (permalink / raw)
  To: netfilter-devel; +Cc: pablo, kaber

These functions allow create a buffer (nftnl_attrbuf) of TLV objects
(nftnl_attr). It is inspired in libmnl/src/attr.c.

Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
---
 include/libnftnl/set.h | 102 ++++++++++++++++++++
 include/set.h          |  23 +++++
 src/libnftnl.map       |  39 ++++++++
 src/set.c              | 246 +++++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 400 insertions(+), 10 deletions(-)

diff --git a/include/libnftnl/set.h b/include/libnftnl/set.h
index 7a5a512..44f411b 100644
--- a/include/libnftnl/set.h
+++ b/include/libnftnl/set.h
@@ -278,4 +278,106 @@ void nft_set_elems_iter_destroy(struct nft_set_elems_iter *iter);
 int nft_set_elems_nlmsg_build_payload_iter(struct nlmsghdr *nlh,
 					   struct nft_set_elems_iter *iter);
 
+/*
+ * nftnl attributes API
+ */
+struct nftnl_attr;
+struct nftnl_attrbuf;
+
+/* nftnl_attrbuf */
+struct nftnl_attrbuf *nftnl_attrbuf_alloc(size_t size);
+void nftnl_attrbuf_delete(struct nftnl_attrbuf *attrbuf);
+void nftnl_attrbuf_free(struct nftnl_attrbuf *attrbuf);
+void nftnl_attrbuf_printf(const struct nftnl_attrbuf *attrbuf);
+size_t nftnl_attrbuf_len(const struct nftnl_attrbuf *attrbuf);
+size_t nftnl_attrbuf_size(const struct nftnl_attrbuf *attrbuf);
+void *nftnl_attrbuf_data(const struct nftnl_attrbuf *attrbuf);
+
+/* TLV attribute getters */
+uint8_t nftnl_attr_get_type(const struct nftnl_attr *attr);
+uint8_t nftnl_attr_get_len(const struct nftnl_attr *attr);
+void *nftnl_attr_get_value(const struct nftnl_attr *attr);
+uint16_t nftnl_attr_get_size(const struct nftnl_attr *attr);
+
+/* TLV attribute putters */
+struct nftnl_attr *nftnl_attr_put(struct nftnl_attrbuf *attrbuf,
+				  uint8_t type, uint8_t len, const void *data);
+struct nftnl_attr *nftnl_attr_put_check(struct nftnl_attrbuf *attrbuf,
+					size_t bufsize, uint8_t type,
+					uint8_t len, const void *data);
+
+/* TLV validation */
+enum nftnl_attr_data_type {
+	NFTNL_ATTR_TYPE_UNSPEC,
+	NFTNL_ATTR_TYPE_U8,
+	NFTNL_ATTR_TYPE_U16,
+	NFTNL_ATTR_TYPE_U32,
+	NFTNL_ATTR_TYPE_U64,
+	NFTNL_ATTR_TYPE_STRING,
+	NFTNL_ATTR_TYPE_BINARY,
+	__NFTNL_ATTR_TYPE_MAX,
+};
+#define NFTNL_ATTR_TYPE_MAX (__NFTNL_ATTR_TYPE_MAX - 1)
+
+int nftnl_attr_type_valid(const struct nftnl_attr *attr);
+int nftnl_attr_validate(const struct nftnl_attr *attr);
+int nftnl_attr_validate2(const struct nftnl_attr *attr, uint8_t exp_len);
+
+/* TLV iterators */
+struct nftnl_attr *nftnl_attr_next(const struct nftnl_attr *attr);
+
+#define nftnl_attr_for_each(attr, attrbuf)                  \
+	for ((attr) = (struct nftnl_attr *)(attrbuf)->data; \
+	     (char *)(attrbuf)->tail > (char *)(attr);      \
+	     (attr) = nftnl_attr_next(attr))
+
+#define nftnl_attr_for_each_payload(attr, payload, payload_len) \
+	for ((attr) = (struct nftnl_attr *)(payload);           \
+	     (char *)(attr) - (char *)(payload) < (payload_len);\
+	     (attr) = nftnl_attr_next(attr))
+
+int nftnl_attr_payload_snprint(const void *payload, size_t payload_len,
+			       char *buf, int bsize);
+/*
+ * Compact
+ */
+struct nft_attr;
+struct nft_attrbuf;
+
+struct nft_attrbuf *nft_attrbuf_alloc(size_t size);
+void nft_attrbuf_delete(struct nft_attrbuf *attrbuf);
+void nft_attrbuf_free(struct nft_attrbuf *attrbuf);
+void nft_attrbuf_printf(const struct nft_attrbuf *attrbuf);
+size_t nft_attrbuf_len(const struct nft_attrbuf *attrbuf);
+size_t nft_attrbuf_size(const struct nft_attrbuf *attrbuf);
+void *nft_attrbuf_data(const struct nft_attrbuf *attrbuf);
+
+/* TLV attribute getters */
+uint8_t nft_attr_get_type(const struct nft_attr *attr);
+uint8_t nft_attr_get_len(const struct nft_attr *attr);
+void *nft_attr_get_value(const struct nft_attr *attr);
+uint16_t nft_attr_get_size(const struct nft_attr *attr);
+
+/* TLV attribute putters */
+struct nft_attr *nft_attr_put(struct nft_attrbuf *attrbuf,
+			      uint8_t type, uint8_t len, const void *data);
+struct nft_attr *nft_attr_put_check(struct nft_attrbuf *attrbuf,
+				    size_t bufsize, uint8_t type,
+				    uint8_t len, const void *data);
+
+/* TLV validation */
+int nft_attr_type_valid(const struct nft_attr *attr);
+int nft_attr_validate(const struct nft_attr *attr);
+int nft_attr_validate2(const struct nft_attr *attr, uint8_t exp_len);
+
+/* TLV iterators */
+struct nft_attr *nft_attr_next(const struct nft_attr *attr);
+
+#define nft_attr_for_each(attr, attrbuf) nftnl_attr_for_each(attr, attrbuf)
+#define nft_attr_for_each_payload(attr, payload, payload_len) \
+	nftnl_attr_for_each_payload(attr, payload, payload_len)
+
+int nft_attr_payload_snprint(const void *payload, size_t payload_len,
+			     char *buf, int bsize);
+
 #endif /* _LIBNFTNL_SET_H_ */
diff --git a/include/set.h b/include/set.h
index 85bd389..48c9199 100644
--- a/include/set.h
+++ b/include/set.h
@@ -35,4 +35,27 @@ struct nftnl_expr;
 int nftnl_set_lookup_id(struct nftnl_expr *e, struct nftnl_set_list *set_list,
 		      uint32_t *set_id);
 
+/*
+ * TLV structures:
+ * nftnl_attr
+ *  <-------- HEADER --------> <------ PAYLOAD ------>
+ * +------------+-------------+- - - - - - - - - - - -+
+ * |    type    |     len     |         value         |
+ * |  (1 byte)  |   (1 byte)  |                       |
+ * +--------------------------+- - - - - - - - - - - -+
+ *  <-- sizeof(nftnl_attr) --> <-- nftnl_attr->len -->
+ *  <------------- nftnl_attr_get_size() ------------>
+ */
+
+struct __attribute__((__packed__)) nftnl_attr {
+	uint8_t type;
+	uint8_t len;
+	unsigned char value[];
+};
+
+struct nftnl_attrbuf {
+	struct nftnl_attr *tail;
+	unsigned char data[];
+};
+
 #endif
diff --git a/src/libnftnl.map b/src/libnftnl.map
index 2e193b7..12dc24e 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -136,6 +136,25 @@ global:
   nft_set_snprintf;
   nft_set_fprintf;
 
+  nft_attrbuf_alloc;
+  nft_attrbuf_delete;
+  nft_attrbuf_free;
+  nft_attrbuf_printf;
+  nft_attrbuf_len;
+  nft_attrbuf_size;
+  nft_attrbuf_data;
+  nft_attr_get_type;
+  nft_attr_get_len;
+  nft_attr_get_value;
+  nft_attr_get_size;
+  nft_attr_put;
+  nft_attr_put_check;
+  nft_attr_type_valid;
+  nft_attr_validate;
+  nft_attr_validate2;
+  nft_attr_next;
+  nft_attr_payload_snprint;
+
   nft_set_list_alloc;
   nft_set_list_free;
   nft_set_list_add;
@@ -336,6 +355,26 @@ global:
   nftnl_set_snprintf;
   nftnl_set_fprintf;
 
+  nftnl_attrbuf_alloc;
+  nftnl_attrbuf_delete;
+  nftnl_attrbuf_free;
+  nftnl_attrbuf_printf;
+  nftnl_attrbuf_len;
+  nftnl_attrbuf_size;
+  nftnl_attrbuf_data;
+  nftnl_attr_get_type;
+  nftnl_attr_get_len;
+  nftnl_attr_get_value;
+  nftnl_attr_get_size;
+  nftnl_attr_put;
+  nftnl_attr_put_check;
+  nftnl_attr_type_valid;
+  nftnl_attr_validate;
+  nftnl_attr_validate2;
+  nftnl_attr_next;
+  nftnl_attr_payload_snprint;
+
+
   nftnl_set_list_alloc;
   nftnl_set_list_free;
   nftnl_set_list_add;
diff --git a/src/set.c b/src/set.c
index 315bced..ca41eb0 100644
--- a/src/set.c
+++ b/src/set.c
@@ -28,6 +28,12 @@
 #include <libnftnl/set.h>
 #include <libnftnl/expr.h>
 
+#define ATTRBUF_ENOUGH_SIZE(attrbuf, bufsize, attr_len) ( \
+	(bufsize) >= \
+		attr_len + \
+		sizeof(struct nftnl_attr) + \
+		nftnl_attrbuf_len(attrbuf))
+
 struct nftnl_set *nftnl_set_alloc(void)
 {
 	struct nftnl_set *s;
@@ -804,7 +810,6 @@ static int nftnl_set_snprintf_json(char *buf, size_t size, struct nftnl_set *s,
 				  uint32_t type, uint32_t flags)
 {
 	int len = size, offset = 0, ret;
-	int i;
 	struct nftnl_set_elem *elem;
 
 	ret = snprintf(buf, len, "{\"set\":{");
@@ -861,18 +866,14 @@ static int nftnl_set_snprintf_json(char *buf, size_t size, struct nftnl_set *s,
 			       s->user.len);
 		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 
-		ret = snprintf(buf + offset, len, ",\"userdata\":\"");
+		ret = snprintf(buf + offset, len, ",\"userdata\":[");
 		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 
-		char *c = s->user.data;
-
-		for (i = 0; i < s->user.len; i++) {
-			ret = snprintf(buf + offset, len, "%c",
-				       isprint(c[i]) ? c[i] : ' ');
-			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-		}
+		ret = nftnl_attr_payload_snprint(s->user.data, s->user.len,
+						 buf + offset, len);
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 
-		ret = snprintf(buf + offset, len, "\"");
+		ret = snprintf(buf + offset, len, "]");
 		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 	}
 
@@ -1270,3 +1271,228 @@ int nftnl_set_lookup_id(struct nftnl_expr *e,
 	*set_id = nftnl_set_get_u32(s, NFTNL_SET_ID);
 	return 1;
 }
+
+/* TLV */
+struct nftnl_attrbuf *nftnl_attrbuf_alloc(size_t size)
+{
+	struct nftnl_attrbuf *attrbuf;
+
+	attrbuf =
+		(struct nftnl_attrbuf *)malloc(sizeof(struct nftnl_attrbuf) +
+					       size
+					      );
+	attrbuf->tail = (struct nftnl_attr *)attrbuf->data;
+
+	return attrbuf;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attrbuf_alloc, nft_attrbuf_alloc);
+
+void nftnl_attrbuf_delete(struct nftnl_attrbuf *attrbuf)
+{
+	attrbuf->tail = (struct nftnl_attr *)attrbuf->data;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attrbuf_delete, nft_attrbuf_delete);
+
+void nftnl_attrbuf_free(struct nftnl_attrbuf *attrbuf)
+{
+	nftnl_attrbuf_delete(attrbuf);
+	free((void *)attrbuf);
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attrbuf_free, nft_attrbuf_free);
+
+size_t nftnl_attrbuf_len(const struct nftnl_attrbuf *attrbuf)
+{
+	return (size_t)((char *)attrbuf->tail - (char *)attrbuf->data);
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attrbuf_len, nft_attrbuf_len);
+
+size_t nftnl_attrbuf_size(const struct nftnl_attrbuf *attrbuf)
+{
+	return (size_t)((char *)attrbuf->tail - (char *)attrbuf);
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attrbuf_size, nft_attrbuf_size);
+
+void *nftnl_attrbuf_data(const struct nftnl_attrbuf *attrbuf)
+{
+	return (void *)attrbuf->data;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attrbuf_data, nft_attrbuf_data);
+
+uint8_t nftnl_attr_get_type(const struct nftnl_attr *attr)
+{
+	return attr->type;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_get_type, nft_attr_get_type);
+
+uint8_t nftnl_attr_get_len(const struct nftnl_attr *attr)
+{
+	return attr->len;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_get_len, nft_attr_get_len);
+
+void *nftnl_attr_get_value(const struct nftnl_attr *attr)
+{
+	return (void *)attr->value;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_get_value, nft_attr_get_value);
+
+uint16_t nftnl_attr_get_size(const struct nftnl_attr *attr)
+{
+	return (char *)nftnl_attr_next(attr) - (char *)attr;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_get_size, nft_attr_get_size);
+
+struct nftnl_attr *nftnl_attr_put(struct nftnl_attrbuf *attrbuf,
+				  uint8_t type, uint8_t len, const void *data)
+{
+	struct nftnl_attr *attr = attrbuf->tail;
+
+	attr->len  = len;
+	attr->type = type;
+	memcpy(attr->value, data, len);
+
+	attrbuf->tail = nftnl_attr_next(attr);
+
+	return attr;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_put, nft_attr_put);
+
+struct nftnl_attr *nftnl_attr_put_check(struct nftnl_attrbuf *attrbuf,
+					size_t bufsize, uint8_t type,
+					uint8_t len, const void *data)
+{
+	if (!ATTRBUF_ENOUGH_SIZE(attrbuf, bufsize, len))
+		return NULL;
+	return nftnl_attr_put(attrbuf, type, len, data);
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_put_check, nft_attr_put_check);
+
+int nftnl_attr_type_valid(const struct nftnl_attr *attr)
+{
+	if (nftnl_attr_get_type(attr) > NFTNL_ATTR_TYPE_MAX) {
+		errno = EINVAL;
+		return -1;
+	}
+	return 1;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_type_valid, nft_attr_type_valid);
+
+static const size_t nftnl_attr_data_type_len[MNL_TYPE_MAX] = {
+	[NFTNL_ATTR_TYPE_U8]	= sizeof(uint8_t),
+	[NFTNL_ATTR_TYPE_U16]	= sizeof(uint16_t),
+	[NFTNL_ATTR_TYPE_U32]	= sizeof(uint32_t),
+	[NFTNL_ATTR_TYPE_U64]	= sizeof(uint64_t),
+};
+
+int nftnl_attr_validate(const struct nftnl_attr *attr)
+{
+	int exp_len;
+
+	exp_len = nftnl_attr_data_type_len[nftnl_attr_get_type(attr)];
+	return nftnl_attr_validate2(attr, exp_len);
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_validate, nft_attr_validate);
+
+int nftnl_attr_validate2(const struct nftnl_attr *attr, uint8_t exp_len)
+{
+	uint8_t type = nftnl_attr_get_type(attr);
+	uint8_t len = nftnl_attr_get_len(attr);
+
+	if (len != exp_len) {
+		errno = ERANGE;
+		return -1;
+	}
+
+	switch (type) {
+	case MNL_TYPE_STRING:
+		if (len == 0) {
+			errno = ERANGE;
+			return -1;
+		}
+		break;
+	default:
+		if (!nftnl_attr_type_valid(attr))
+			return -1;
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_validate2, nft_attr_validate2);
+
+struct nftnl_attr *nftnl_attr_next(const struct nftnl_attr *attr)
+{
+	return (struct nftnl_attr *)&attr->value[attr->len];
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_next, nft_attr_next);
+
+static int __attr_snprint(const struct nftnl_attr *attr,
+			char *buf, size_t bsize)
+{
+	int i;
+	int written, blen, boffset;
+	uint8_t alen;
+	char *aval;
+
+	written = 0;
+	boffset = 0;
+	blen = bsize;
+	alen = nftnl_attr_get_len(attr);
+	aval = (char *)nftnl_attr_get_value(attr);
+
+
+	/* type */
+	written = snprintf(buf + boffset, blen, "{\"type\":%u,",
+			   nftnl_attr_get_type(attr));
+	SNPRINTF_BUFFER_SIZE(written, bsize, blen, boffset);
+
+	/* len */
+	written = snprintf(buf + boffset, blen, "\"len\":%u,", alen);
+	SNPRINTF_BUFFER_SIZE(written, bsize, blen, boffset);
+
+	/* value as string */
+	written = snprintf(buf + boffset, blen, "\"val\":");
+	SNPRINTF_BUFFER_SIZE(written, bsize, blen, boffset);
+
+	written = snprintf(buf + boffset, blen, "\"");
+	SNPRINTF_BUFFER_SIZE(written, bsize, blen, boffset);
+
+	for (i = 0; i < alen; i++) {
+		written = snprintf(buf + boffset, blen, "%c",
+				   isprint(aval[i]) ? aval[i] : ' ');
+		SNPRINTF_BUFFER_SIZE(written, bsize, blen, boffset);
+	}
+
+	written = snprintf(buf + boffset, blen, "\"");
+	SNPRINTF_BUFFER_SIZE(written, bsize, blen, boffset);
+
+	written = snprintf(buf + boffset, blen, "}");
+	SNPRINTF_BUFFER_SIZE(written, bsize, blen, boffset);
+
+	return boffset;
+}
+
+int nftnl_attr_payload_snprint(const void *payload, size_t payload_len,
+			       char *buf, int bsize)
+{
+	struct nftnl_attr *attr;
+	int written, blen, boffset;
+
+	written = 0;
+	boffset = 0;
+	blen = bsize;
+
+	nftnl_attr_for_each_payload(attr, payload, payload_len) {
+		written = __attr_snprint(attr, buf + boffset, blen);
+		SNPRINTF_BUFFER_SIZE(written, bsize, blen, boffset);
+
+		written = snprintf(buf + boffset, blen, ",");
+		SNPRINTF_BUFFER_SIZE(written, bsize, blen, boffset);
+	}
+	/* delete last comma */
+	if (boffset)
+		boffset--;
+
+	return boffset;
+}
+EXPORT_SYMBOL_ALIAS(nftnl_attr_payload_snprint, nft_attr_payload_snprint);
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/4 v2] libnftnl: set: Implement new buffer of TLV objects.
  2016-01-05 13:03 ` [PATCH 3/4 v2] libnftnl: set: Implement new buffer of TLV objects Carlos Falgueras García
@ 2016-01-05 13:28   ` Florian Westphal
  2016-01-08 13:41     ` Pablo Neira Ayuso
  0 siblings, 1 reply; 4+ messages in thread
From: Florian Westphal @ 2016-01-05 13:28 UTC (permalink / raw)
  To: Carlos Falgueras García; +Cc: netfilter-devel, pablo, kaber

Carlos Falgueras García <carlosfg@riseup.net> wrote:
> These functions allow create a buffer (nftnl_attrbuf) of TLV objects
> (nftnl_attr). It is inspired in libmnl/src/attr.c.

It would be nice to get a summary on how this going to be used.

At this time I don't understand why nftnl needs this api,
the kernel doesn't enforce any format on this data (good), so we cannot
rely on it having any specific format when reading arbitrary userdata
(added by someone else).

> +EXPORT_SYMBOL_ALIAS(nftnl_attrbuf_alloc, nft_attrbuf_alloc);

This should be plain EXPORT_SYMBOL everywhere, ALIAS is just
for backwards compat.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/4 v2] libnftnl: set: Implement new buffer of TLV objects.
  2016-01-05 13:28   ` Florian Westphal
@ 2016-01-08 13:41     ` Pablo Neira Ayuso
  0 siblings, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 13:41 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Carlos Falgueras García, netfilter-devel, kaber

Hi Florian,

On Tue, Jan 05, 2016 at 02:28:47PM +0100, Florian Westphal wrote:
> Carlos Falgueras García <carlosfg@riseup.net> wrote:
> > These functions allow create a buffer (nftnl_attrbuf) of TLV objects
> > (nftnl_attr). It is inspired in libmnl/src/attr.c.
> 
> It would be nice to get a summary on how this going to be used.
> 
> At this time I don't understand why nftnl needs this api,
> the kernel doesn't enforce any format on this data (good), so we cannot
> rely on it having any specific format when reading arbitrary userdata
> (added by someone else).

Since the introduction of concatenations, the NFTA_SET_DATA_TYPE
attribute became too short to store the datatype information that we
need to keep to interpret the elements datatypes. This field is very
useful when dumping things from the kernel, to interpret them given
that the kernel side has no understanding on the byte semantics that
it is storing.

Another problem is that we also don't want to have fixed integer
datatypes since we can also have header bitfields into sets, this
would also explode in number when consider host and network byteorder
variants, so the idea is to store this in flexible TLV format in the
set userdata area.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2016-01-08 13:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-05 13:03 [PATCH 1/4 v2] nf: netfilter: nf_tables_api: Add new attributes into nft_set to store user data Carlos Falgueras García
2016-01-05 13:03 ` [PATCH 3/4 v2] libnftnl: set: Implement new buffer of TLV objects Carlos Falgueras García
2016-01-05 13:28   ` Florian Westphal
2016-01-08 13:41     ` 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.