netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] libnftnl: Implement new buffer of TLV objects.
@ 2016-02-20 22:43 Carlos Falgueras García
  2016-02-20 22:43 ` [PATCH 1/2] libnftnl: rule: Change the "userdata" attribute to use new TLV buffer Carlos Falgueras García
  2016-02-20 22:43 ` [PATCH 2/2] nftables: rule: Change the field "rule->comment" for an nftnl_attrbuf Carlos Falgueras García
  0 siblings, 2 replies; 3+ messages in thread
From: Carlos Falgueras García @ 2016-02-20 22:43 UTC (permalink / raw)
  To: netfilter-devel; +Cc: pablo, kaber

These functions allow to create a buffer (nftnl_attrbuf) of TLV objects
(nftnl_attr). It is inspired by libmnl/src/attr.c. It can be used to store
several variable length user data into an object.

Example usage:
	```
	struct nftnl_attrbuf *attrbuf;
	struct nftnl_attr *attr;
	const char str[] = "Hello World!";

	attrbuf = nftnl_attrbuf_alloc(ATTRBUF_SIZE);
	if (!nftnl_attr_put_check(attrbuf, NFTNL_ATTR_TYPE_COMMENT,
				  strlen(str), str)
	) {
		fprintf(stderr, "Can't put attribute \"%s\"", str);
	}

	nftnl_attr_for_each(attr, attrbuf) {
		printf("%s\n", (char *)nftnl_attr_get_value(attr));
	}

	nftnl_attr_free(attrbuf);
	```

Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
---
 include/Makefile.am          |   1 +
 include/attr.h               |  40 +++++++++++++
 include/libnftnl/Makefile.am |   1 +
 include/libnftnl/attr.h      |  59 +++++++++++++++++++
 src/Makefile.am              |   1 +
 src/attr.c                   | 132 +++++++++++++++++++++++++++++++++++++++++++
 src/libnftnl.map             |  16 ++++++
 7 files changed, 250 insertions(+)
 create mode 100644 include/attr.h
 create mode 100644 include/libnftnl/attr.h
 create mode 100644 src/attr.c

diff --git a/include/Makefile.am b/include/Makefile.am
index be9eb9b..785ec15 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -12,4 +12,5 @@ noinst_HEADERS = internal.h	\
 		 expr.h		\
 		 json.h		\
 		 set_elem.h	\
+		 attr.h		\
 		 utils.h
diff --git a/include/attr.h b/include/attr.h
new file mode 100644
index 0000000..2a29fa0
--- /dev/null
+++ b/include/attr.h
@@ -0,0 +1,40 @@
+#ifndef _LIBNFTNL_ATTR_INTERNAL_H_
+#define _LIBNFTNL_ATTR_INTERNAL_H_
+
+#include <stdint.h>
+#include <stddef.h>
+
+/*
+ * TLV structures:
+ * nftnl_attr
+ *  <-------- HEADER --------> <------ PAYLOAD ------>
+ * +------------+-------------+- - - - - - - - - - - -+
+ * |    type    |     len     |         value         |
+ * |  (1 byte)  |   (1 byte)  |                       |
+ * +--------------------------+- - - - - - - - - - - -+
+ *  <-- sizeof(nftnl_attr) --> <-- nftnl_attr->len -->
+ */
+struct __attribute__((__packed__)) nftnl_attr {
+	uint8_t type;
+	uint8_t len;
+	unsigned char value[];
+};
+
+/*
+ *              +-------------------------------------------++
+ *              |           data[]                          ||
+ *              |             ||                            ||
+ *              |             \/                            \/
+ *  +-------+-------+- - - - -+-------+-------+ ... +-------+- - - - - - -+
+ *  | size  |  end  | padding |  TLV  |  TLV  |     |  TLV  |    Empty    |
+ *  +-------+-------+- - - - -+-------+-------+ ... +-------+- - - - - - -+
+ *                            |<- nftnl_attrbuf_get_len() ->|
+ *                            |<-------- nftnl_attrbuf_get_size() ------->|
+ */
+struct nftnl_attrbuf {
+	size_t size;
+	char  *end;
+	char   data[] __attribute__((aligned(64)));
+};
+
+#endif
diff --git a/include/libnftnl/Makefile.am b/include/libnftnl/Makefile.am
index 84f01b6..a3a6fb3 100644
--- a/include/libnftnl/Makefile.am
+++ b/include/libnftnl/Makefile.am
@@ -7,4 +7,5 @@ pkginclude_HEADERS = batch.h		\
 		     set.h		\
 		     ruleset.h		\
 		     common.h		\
+		     attr.h		\
 		     gen.h
diff --git a/include/libnftnl/attr.h b/include/libnftnl/attr.h
new file mode 100644
index 0000000..a99185a
--- /dev/null
+++ b/include/libnftnl/attr.h
@@ -0,0 +1,59 @@
+#ifndef _LIBNFTNL_ATTR_H_
+#define _LIBNFTNL_ATTR_H_
+
+#include <stdio.h>
+#include <stdint.h>
+
+/*
+ * nftnl attributes API
+ */
+struct nftnl_attr;
+struct nftnl_attrbuf;
+
+/* nftnl_attrbuf */
+struct nftnl_attrbuf *nftnl_attrbuf_alloc(size_t data_size);
+void nftnl_attrbuf_free(struct nftnl_attrbuf *attrbuf);
+size_t nftnl_attrbuf_get_len(const struct nftnl_attrbuf *attrbuf);
+size_t nftnl_attrbuf_get_size(const struct nftnl_attrbuf *attrbuf);
+void *nftnl_attrbuf_get_data(const struct nftnl_attrbuf *attrbuf);
+void nftnl_attrbuf_copy_data(struct nftnl_attrbuf *attrbuf,
+			     const void *data, size_t len);
+struct nftnl_attr *nftnl_attrbuf_get_start(const struct nftnl_attrbuf *attrbuf);
+struct nftnl_attr *nftnl_attrbuf_get_end(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);
+
+/* TLV attribute putters */
+struct nftnl_attr *nftnl_attr_put(struct nftnl_attrbuf *attrbuf,
+				  uint8_t type, uint8_t len, const void *value);
+struct nftnl_attr *nftnl_attr_put_check(struct nftnl_attrbuf *attrbuf,
+					uint8_t type, size_t len,
+					const void *value);
+
+enum nftnl_attr_data_type {
+	NFTNL_ATTR_TYPE_COMMENT,
+	__NFTNL_ATTR_TYPE_MAX,
+};
+#define NFTNL_ATTR_TYPE_MAX (__NFTNL_ATTR_TYPE_MAX - 1)
+
+/* TLV iterators */
+struct nftnl_attr *nftnl_attr_next(const struct nftnl_attr *attr);
+
+#define nftnl_attr_for_each(attr, attrbuf)                              \
+	for ((attr) = nftnl_attrbuf_get_start(attrbuf);                 \
+	     (char *)(nftnl_attrbuf_get_end(attrbuf)) > (char *)(attr); \
+	     (attr) = nftnl_attr_next(attr))
+
+/* TLV callback-based attribute parsers */
+#define NFTNL_CB_ERROR	-1
+#define NFTNL_CB_STOP	 0
+#define NFTNL_CB_OK	 1
+
+typedef int (*nftnl_attr_cb_t)(const struct nftnl_attr *attr, void *data);
+int nftnl_attr_parse(const struct nftnl_attrbuf *attrbuf, nftnl_attr_cb_t cb,
+		     void *data);
+
+#endif /* _LIBNFTNL_ATTR_H_ */
diff --git a/src/Makefile.am b/src/Makefile.am
index a27e292..621dd69 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,7 @@ libnftnl_la_SOURCES = utils.c		\
 		      ruleset.c		\
 		      mxml.c		\
 		      jansson.c		\
+		      attr.c		\
 		      expr.c		\
 		      expr_ops.c	\
 		      expr/bitwise.c	\
diff --git a/src/attr.c b/src/attr.c
new file mode 100644
index 0000000..82c63aa
--- /dev/null
+++ b/src/attr.c
@@ -0,0 +1,132 @@
+#include <libnftnl/attr.h>
+#include <attr.h>
+#include <utils.h>
+
+#include <stdlib.h>
+#include <stdint.h>
+
+
+struct nftnl_attrbuf *nftnl_attrbuf_alloc(size_t data_size)
+{
+	struct nftnl_attrbuf *attrbuf;
+
+	attrbuf = (struct nftnl_attrbuf *)
+		malloc(sizeof(struct nftnl_attrbuf) + data_size);
+	attrbuf->size = data_size;
+	attrbuf->end = attrbuf->data;
+
+	return attrbuf;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_alloc);
+
+void nftnl_attrbuf_free(struct nftnl_attrbuf *attrbuf)
+{
+	attrbuf->size = 0;
+	attrbuf->end = NULL;
+	free((void *)attrbuf);
+}
+EXPORT_SYMBOL(nftnl_attrbuf_free);
+
+size_t nftnl_attrbuf_get_len(const struct nftnl_attrbuf *attrbuf)
+{
+	return (size_t)(attrbuf->end - attrbuf->data);
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_len);
+
+size_t nftnl_attrbuf_get_size(const struct nftnl_attrbuf *attrbuf)
+{
+	return attrbuf->size;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_size);
+
+struct nftnl_attr *nftnl_attrbuf_get_start(const struct nftnl_attrbuf *attrbuf)
+{
+	return (struct nftnl_attr *)attrbuf->data;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_start);
+
+struct nftnl_attr *nftnl_attrbuf_get_end(const struct nftnl_attrbuf *attrbuf)
+{
+	return (struct nftnl_attr *)attrbuf->end;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_end);
+
+void *nftnl_attrbuf_get_data(const struct nftnl_attrbuf *attrbuf)
+{
+	return (void *)attrbuf->data;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_data);
+
+void nftnl_attrbuf_copy_data(struct nftnl_attrbuf *attrbuf,
+			    const void *data, size_t len)
+{
+	memcpy(attrbuf->data, data, len <= attrbuf->size ? len : attrbuf->size);
+	attrbuf->end = attrbuf->data + len;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_copy_data);
+
+uint8_t nftnl_attr_get_type(const struct nftnl_attr *attr)
+{
+	return attr->type;
+}
+EXPORT_SYMBOL(nftnl_attr_get_type);
+
+uint8_t nftnl_attr_get_len(const struct nftnl_attr *attr)
+{
+	return attr->len;
+}
+EXPORT_SYMBOL(nftnl_attr_get_len);
+
+void *nftnl_attr_get_value(const struct nftnl_attr *attr)
+{
+	return (void *)attr->value;
+}
+EXPORT_SYMBOL(nftnl_attr_get_value);
+
+struct nftnl_attr *nftnl_attr_put(struct nftnl_attrbuf *attrbuf,
+				  uint8_t type, uint8_t len, const void *value)
+{
+	struct nftnl_attr *attr = (struct nftnl_attr *)attrbuf->end;
+
+	attr->len  = len;
+	attr->type = type;
+	memcpy(attr->value, value, len);
+
+	attrbuf->end = (char *)nftnl_attr_next(attr);
+
+	return attr;
+}
+EXPORT_SYMBOL(nftnl_attr_put);
+
+struct nftnl_attr *nftnl_attr_put_check(struct nftnl_attrbuf *attrbuf,
+					uint8_t type, size_t len,
+					const void *value)
+{
+	/* Check if there is enough space */
+	if (attrbuf->size < len + sizeof(struct nftnl_attr))
+		return NULL;
+
+	return nftnl_attr_put(attrbuf, type, len, value);
+}
+EXPORT_SYMBOL(nftnl_attr_put_check);
+
+struct nftnl_attr *nftnl_attr_next(const struct nftnl_attr *attr)
+{
+	return (struct nftnl_attr *)&attr->value[attr->len];
+}
+EXPORT_SYMBOL(nftnl_attr_next);
+
+int nftnl_attr_parse(const struct nftnl_attrbuf *attrbuf, nftnl_attr_cb_t cb,
+		     void *data)
+{
+	int ret = NFTNL_CB_OK;
+	const struct nftnl_attr *attr;
+
+	nftnl_attr_for_each(attr, attrbuf) {
+		ret = cb(attr, data);
+		if (ret <= NFTNL_CB_STOP)
+			return ret;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(nftnl_attr_parse);
diff --git a/src/libnftnl.map b/src/libnftnl.map
index 2e193b7..65bd37e 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -336,6 +336,22 @@ global:
   nftnl_set_snprintf;
   nftnl_set_fprintf;
 
+  nftnl_attrbuf_alloc;
+  nftnl_attrbuf_free;
+  nftnl_attrbuf_get_len;
+  nftnl_attrbuf_get_size;
+  nftnl_attrbuf_get_data;
+  nftnl_attrbuf_copy_data;
+  nftnl_attrbuf_get_start;
+  nftnl_attrbuf_get_end;
+  nftnl_attr_get_type;
+  nftnl_attr_get_len;
+  nftnl_attr_get_value;
+  nftnl_attr_put;
+  nftnl_attr_put_check;
+  nftnl_attr_next;
+  nftnl_attr_parse;
+
   nftnl_set_list_alloc;
   nftnl_set_list_free;
   nftnl_set_list_add;
-- 
2.7.0

--
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] 3+ messages in thread

* [PATCH 1/2] libnftnl: rule: Change the "userdata" attribute to use new TLV buffer.
  2016-02-20 22:43 [PATCH] libnftnl: Implement new buffer of TLV objects Carlos Falgueras García
@ 2016-02-20 22:43 ` Carlos Falgueras García
  2016-02-20 22:43 ` [PATCH 2/2] nftables: rule: Change the field "rule->comment" for an nftnl_attrbuf Carlos Falgueras García
  1 sibling, 0 replies; 3+ messages in thread
From: Carlos Falgueras García @ 2016-02-20 22:43 UTC (permalink / raw)
  To: netfilter-devel; +Cc: pablo, kaber

Now is it possible to store multiple variable length user data into a rule.

Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
---
 src/rule.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 130 insertions(+), 28 deletions(-)

diff --git a/src/rule.c b/src/rule.c
index 3a32bf6..4e6f375 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -28,6 +28,7 @@
 #include <libnftnl/rule.h>
 #include <libnftnl/set.h>
 #include <libnftnl/expr.h>
+#include <libnftnl/attr.h>
 
 struct nftnl_rule {
 	struct list_head head;
@@ -38,10 +39,7 @@ struct nftnl_rule {
 	const char	*chain;
 	uint64_t	handle;
 	uint64_t	position;
-	struct {
-			void		*data;
-			uint32_t	len;
-	} user;
+	struct nftnl_attrbuf	*userdata;
 	struct {
 			uint32_t	flags;
 			uint32_t	proto;
@@ -50,6 +48,14 @@ struct nftnl_rule {
 	struct list_head expr_list;
 };
 
+static void nftnl_rule_parse_userdata(const struct nftnl_attrbuf *attrbuf,
+				      const struct nftnl_attr *tb[]);
+static size_t nftnl_rule_snprintf_data2str(char *buf, size_t size,
+					   const void *data, size_t datalen);
+static size_t nftnl_rule_snprintf_userdata(char *buf, size_t size,
+					   const struct nftnl_attr *tb[],
+					   enum nftnl_attr_data_type dtype);
+
 struct nftnl_rule *nftnl_rule_alloc(void)
 {
 	struct nftnl_rule *r;
@@ -75,6 +81,8 @@ void nftnl_rule_free(struct nftnl_rule *r)
 		xfree(r->table);
 	if (r->chain != NULL)
 		xfree(r->chain);
+	if (r->flags & (1 << NFTNL_RULE_USERDATA))
+		nftnl_attrbuf_free(r->userdata);
 
 	xfree(r);
 }
@@ -162,8 +170,12 @@ void nftnl_rule_set_data(struct nftnl_rule *r, uint16_t attr,
 		r->position = *((uint64_t *)data);
 		break;
 	case NFTNL_RULE_USERDATA:
-		r->user.data = (void *)data;
-		r->user.len = data_len;
+		(r->userdata = nftnl_attrbuf_alloc(data_len));
+		if (!r->userdata) {
+			perror("nftnl_rule_set_data - userdata");
+			exit(EXIT_FAILURE);
+		}
+		nftnl_attrbuf_copy_data(r->userdata, data, data_len);
 		break;
 	}
 	r->flags |= (1 << attr);
@@ -221,8 +233,8 @@ const void *nftnl_rule_get_data(const struct nftnl_rule *r, uint16_t attr,
 		*data_len = sizeof(uint64_t);
 		return &r->position;
 	case NFTNL_RULE_USERDATA:
-		*data_len = r->user.len;
-		return r->user.data;
+		*data_len = nftnl_attrbuf_get_len(r->userdata);
+		return (void *)nftnl_attrbuf_get_data(r->userdata);
 	}
 	return NULL;
 }
@@ -288,8 +300,9 @@ void nftnl_rule_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_rule *r)
 	if (r->flags & (1 << NFTNL_RULE_POSITION))
 		mnl_attr_put_u64(nlh, NFTA_RULE_POSITION, htobe64(r->position));
 	if (r->flags & (1 << NFTNL_RULE_USERDATA)) {
-		mnl_attr_put(nlh, NFTA_RULE_USERDATA, r->user.len,
-			     r->user.data);
+		mnl_attr_put(nlh, NFTA_RULE_USERDATA,
+			     nftnl_attrbuf_get_len(r->userdata),
+			     nftnl_attrbuf_get_data(r->userdata));
 	}
 
 	if (!list_empty(&r->expr_list)) {
@@ -447,19 +460,17 @@ int nftnl_rule_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_rule *r)
 		r->flags |= (1 << NFTNL_RULE_POSITION);
 	}
 	if (tb[NFTA_RULE_USERDATA]) {
+		uint16_t udata_size;
 		const void *udata =
 			mnl_attr_get_payload(tb[NFTA_RULE_USERDATA]);
 
-		if (r->user.data)
-			xfree(r->user.data);
-
-		r->user.len = mnl_attr_get_payload_len(tb[NFTA_RULE_USERDATA]);
+		udata_size = mnl_attr_get_payload_len(tb[NFTA_RULE_USERDATA]);
 
-		r->user.data = malloc(r->user.len);
-		if (r->user.data == NULL)
+		(r->userdata = nftnl_attrbuf_alloc(udata_size));
+		if (!r->userdata)
 			return -1;
+		nftnl_attrbuf_copy_data(r->userdata, udata, udata_size);
 
-		memcpy(r->user.data, udata, r->user.len);
 		r->flags |= (1 << NFTNL_RULE_USERDATA);
 	}
 
@@ -757,6 +768,29 @@ static int nftnl_rule_snprintf_json(char *buf, size_t size, struct nftnl_rule *r
 		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 	}
 
+	if (r->flags & (1 << NFTNL_RULE_USERDATA)) {
+		const struct nftnl_attr *tb[NFTNL_ATTR_TYPE_MAX+1] = {NULL};
+
+		nftnl_rule_parse_userdata(r->userdata, tb);
+
+		ret = snprintf(buf+offset, len, "\"userdata\":[");
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+		if (tb[NFTNL_ATTR_TYPE_COMMENT]) {
+			ret = snprintf(buf+offset, len, "{\"comment\":\"");
+			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+			ret = nftnl_rule_snprintf_userdata(buf+offset, size, tb,
+						NFTNL_ATTR_TYPE_COMMENT);
+			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+			ret = snprintf(buf+offset, len, "\"}");
+			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+		}
+
+		ret = snprintf(buf+offset, len, "],\n");
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+	}
+
 	ret = snprintf(buf+offset, len, "\"expr\":[");
 	SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 
@@ -855,11 +889,76 @@ static int nftnl_rule_snprintf_xml(char *buf, size_t size, struct nftnl_rule *r,
 	return offset;
 }
 
+static int nftnl_rule_parse_userdata_cb(const struct nftnl_attr *attr,
+					void *data)
+{
+	const struct nftnl_attr **tb = data;
+	uint8_t type = nftnl_attr_get_type(attr);
+	uint8_t len = nftnl_attr_get_len(attr);
+	unsigned char *value = nftnl_attr_get_value(attr);
+
+	/* Validation */
+	switch (type) {
+	case NFTNL_ATTR_TYPE_COMMENT:
+		if (value[len-1] != '\0')
+			return NFTNL_CB_ERROR;
+	default:
+		return NFTNL_CB_ERROR;
+	};
+
+	tb[type] = attr;
+	return NFTNL_CB_OK;
+}
+
+static void nftnl_rule_parse_userdata(const struct nftnl_attrbuf *attrbuf,
+				      const struct nftnl_attr *tb[])
+{
+	if (nftnl_attr_parse(attrbuf, nftnl_rule_parse_userdata_cb, tb)
+		!= NFTNL_CB_OK
+	) {
+		fprintf(stderr, "Error parsing rule userdata\n");
+		exit(EXIT_FAILURE);
+	}
+}
+
+static size_t nftnl_rule_snprintf_data2str(char *buf, size_t size,
+					   const void *data, size_t datalen)
+{
+	int i;
+	size_t ret, len = size, offset = 0;
+	const char *c = data;
+
+	for (i = 0; i < datalen; i++) {
+		ret = snprintf(buf+offset, len, "%c",
+			       isprint(c[i]) ? c[i] : '?');
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+	}
+
+	return offset;
+}
+
+static size_t nftnl_rule_snprintf_userdata(char *buf, size_t size,
+					   const struct nftnl_attr *tb[],
+					   enum nftnl_attr_data_type dtype)
+{
+	size_t ret, offset = 0;
+
+	ret = nftnl_rule_snprintf_data2str(
+		buf,
+		size,
+		nftnl_attr_get_value(tb[dtype]),
+		nftnl_attr_get_len(tb[dtype])-1
+	);
+	SNPRINTF_BUFFER_SIZE(ret, size, size, offset);
+
+	return offset;
+}
+
 static int nftnl_rule_snprintf_default(char *buf, size_t size, struct nftnl_rule *r,
 				     uint32_t type, uint32_t flags)
 {
 	struct nftnl_expr *expr;
-	int ret, len = size, offset = 0, i;
+	int ret, len = size, offset = 0;
 
 	if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
 		ret = snprintf(buf+offset, len, "%s ",
@@ -905,20 +1004,23 @@ static int nftnl_rule_snprintf_default(char *buf, size_t size, struct nftnl_rule
 		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 	}
 
-	if (r->user.len) {
-		ret = snprintf(buf+offset, len, "  userdata = { ");
-		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 
-		for (i = 0; i < r->user.len; i++) {
-			char *c = r->user.data;
+	if (r->flags & (1 << NFTNL_RULE_USERDATA)) {
+		const struct nftnl_attr *tb[NFTNL_ATTR_TYPE_MAX+1] = {NULL};
+
+		nftnl_rule_parse_userdata(r->userdata, tb);
 
-			ret = snprintf(buf+offset, len, "%c",
-				       isalnum(c[i]) ? c[i] : 0);
+		if (tb[NFTNL_ATTR_TYPE_COMMENT]) {
+			ret = snprintf(buf+offset, len, "  userdata = { ");
 			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-		}
 
-		ret = snprintf(buf+offset, len, " }\n");
-		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+			ret = nftnl_rule_snprintf_userdata(buf+offset, size, tb,
+						NFTNL_ATTR_TYPE_COMMENT);
+			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+			ret = snprintf(buf+offset, len, " }\n");
+			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+		}
 
 	}
 
-- 
2.7.0

--
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] 3+ messages in thread

* [PATCH 2/2] nftables: rule: Change the field "rule->comment" for an nftnl_attrbuf.
  2016-02-20 22:43 [PATCH] libnftnl: Implement new buffer of TLV objects Carlos Falgueras García
  2016-02-20 22:43 ` [PATCH 1/2] libnftnl: rule: Change the "userdata" attribute to use new TLV buffer Carlos Falgueras García
@ 2016-02-20 22:43 ` Carlos Falgueras García
  1 sibling, 0 replies; 3+ messages in thread
From: Carlos Falgueras García @ 2016-02-20 22:43 UTC (permalink / raw)
  To: netfilter-devel; +Cc: pablo, kaber

Now it is possible to store multiple variable length user data into rule.
Modify the parser in order to fill the nftnl_attrbuf with the comment, and
the print function for extract these commentary and print it to user.

Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
---
 include/rule.h            |  7 +++++--
 src/netlink_delinearize.c |  7 +++++--
 src/netlink_linearize.c   |  6 ++++--
 src/parser_bison.y        | 17 ++++++++++++++++-
 src/rule.c                | 28 +++++++++++++++++++++++++---
 5 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index c848f0f..96086ab 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -4,6 +4,7 @@
 #include <stdint.h>
 #include <nftables.h>
 #include <list.h>
+#include <libnftnl/attr.h>
 
 /**
  * struct handle - handle for tables, chains, rules and sets
@@ -155,7 +156,7 @@ extern void chain_print_plain(const struct chain *chain);
  * @location:	location the rule was defined at
  * @stmt:	list of statements
  * @num_stmts:	number of statements in stmts list
- * @comment:	comment
+ * @udata:	user data
  */
 struct rule {
 	struct list_head	list;
@@ -163,9 +164,11 @@ struct rule {
 	struct location		location;
 	struct list_head	stmts;
 	unsigned int		num_stmts;
-	const char		*comment;
+	struct nftnl_attrbuf	*udata;
 };
 
+#define RULE_UDATA_MAX_LEN 256
+
 extern struct rule *rule_alloc(const struct location *loc,
 			       const struct handle *h);
 extern void rule_free(struct rule *rule);
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index ae6abb0..c7448d3 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -25,6 +25,7 @@
 #include <utils.h>
 #include <erec.h>
 #include <sys/socket.h>
+#include <libnftnl/attr.h>
 
 struct netlink_parse_ctx {
 	struct list_head	*msgs;
@@ -1738,8 +1739,10 @@ struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
 		uint32_t len;
 
 		data = nftnl_rule_get_data(nlr, NFTNL_RULE_USERDATA, &len);
-		pctx->rule->comment = xmalloc(len);
-		memcpy((char *)pctx->rule->comment, data, len);
+		pctx->rule->udata = nftnl_attrbuf_alloc(len);
+		if (!pctx->rule->udata)
+			memory_allocation_error();
+		nftnl_attrbuf_copy_data(pctx->rule->udata, data, len);
 	}
 
 	nftnl_expr_foreach((struct nftnl_rule *)nlr, netlink_parse_expr, pctx);
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 86b49c6..7b33f33 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -21,6 +21,7 @@
 #include <netinet/in.h>
 
 #include <linux/netfilter.h>
+#include <libnftnl/attr.h>
 
 
 struct netlink_linearize_ctx {
@@ -1108,9 +1109,10 @@ void netlink_linearize_rule(struct netlink_ctx *ctx, struct nftnl_rule *nlr,
 	list_for_each_entry(stmt, &rule->stmts, list)
 		netlink_gen_stmt(&lctx, stmt);
 
-	if (rule->comment)
+	if (rule->udata)
 		nftnl_rule_set_data(nlr, NFTNL_RULE_USERDATA,
-				    rule->comment, strlen(rule->comment) + 1);
+				    nftnl_attrbuf_get_data(rule->udata),
+				    nftnl_attrbuf_get_len(rule->udata));
 
 	netlink_dump_rule(nlr);
 }
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 05ade0f..8990975 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -24,6 +24,7 @@
 #include <netinet/icmp6.h>
 #include <libnftnl/common.h>
 #include <libnftnl/set.h>
+#include <libnftnl/attr.h>
 
 #include <rule.h>
 #include <statement.h>
@@ -1304,7 +1305,21 @@ rule			:	stmt_list	comment_spec
 				struct stmt *i;
 
 				$$ = rule_alloc(&@$, NULL);
-				$$->comment = $2;
+
+				if ($2) {
+					if (!($$->udata = nftnl_attrbuf_alloc(RULE_UDATA_MAX_LEN)))
+						memory_allocation_error();
+
+					if (!(nftnl_attr_put_check($$->udata,
+						NFTNL_ATTR_TYPE_COMMENT,
+						strlen($2) + 1, $2))
+					) {
+						erec_queue(error(&@2, "Comment too long: \"%s\"", $2),
+							state->msgs);
+						YYERROR;
+					}
+				}
+
 				list_for_each_entry(i, $1, list)
 					$$->num_stmts++;
 				list_splice_tail($1, &$$->stmts);
diff --git a/src/rule.c b/src/rule.c
index 18ff592..8ca4bb0 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -23,6 +23,7 @@
 
 #include <libnftnl/common.h>
 #include <libnftnl/ruleset.h>
+#include <libnftnl/attr.h>
 #include <netinet/ip.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_arp.h>
@@ -366,6 +367,7 @@ struct rule *rule_alloc(const struct location *loc, const struct handle *h)
 	rule->location = *loc;
 	init_list_head(&rule->list);
 	init_list_head(&rule->stmts);
+	rule->udata = NULL;
 	if (h != NULL)
 		rule->handle = *h;
 	return rule;
@@ -375,21 +377,41 @@ void rule_free(struct rule *rule)
 {
 	stmt_list_free(&rule->stmts);
 	handle_free(&rule->handle);
-	xfree(rule->comment);
+	nftnl_attrbuf_free(rule->udata);
 	xfree(rule);
 }
 
+static int rule_parse_userdata_cb(const struct nftnl_attr *attr,
+				  void *data)
+{
+	const struct nftnl_attr **tb = data;
+	uint8_t type = nftnl_attr_get_type(attr);
+
+	tb[type] = attr;
+	return NFTNL_CB_OK;
+}
+
+
 void rule_print(const struct rule *rule)
 {
 	const struct stmt *stmt;
+	const struct nftnl_attr *tb[NFTNL_ATTR_TYPE_MAX+1] = {};
+	const struct nftnl_attr *attr;
 
 	list_for_each_entry(stmt, &rule->stmts, list) {
 		stmt->ops->print(stmt);
 		printf(" ");
 	}
 
-	if (rule->comment)
-		printf("comment \"%s\" ", rule->comment);
+	if (rule->udata) {
+		if (nftnl_attr_parse(rule->udata, rule_parse_userdata_cb, tb)
+			!= NFTNL_CB_ERROR
+		) {
+			attr = tb[NFTNL_ATTR_TYPE_COMMENT];
+			printf("comment \"%s\" ",
+					(char *)nftnl_attr_get_value(attr));
+		}
+	}
 
 	if (handle_output > 0)
 		printf("# handle %" PRIu64, rule->handle.handle);
-- 
2.7.0

--
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] 3+ messages in thread

end of thread, other threads:[~2016-02-20 22:44 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-20 22:43 [PATCH] libnftnl: Implement new buffer of TLV objects Carlos Falgueras García
2016-02-20 22:43 ` [PATCH 1/2] libnftnl: rule: Change the "userdata" attribute to use new TLV buffer Carlos Falgueras García
2016-02-20 22:43 ` [PATCH 2/2] nftables: rule: Change the field "rule->comment" for an nftnl_attrbuf Carlos Falgueras García

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).