diff mbox

[1/2] set: Implement new buffer of TLV objects.

Message ID 1454614720-8126-1-git-send-email-carlosfg@riseup.net
State Changes Requested
Delegated to: Pablo Neira
Headers show

Commit Message

Carlos Falgueras García Feb. 4, 2016, 7:38 p.m. UTC
These functions allow to create a buffer (nftnl_attrbuf) of TLV objects
(nftnl_attr). It is inspired by libmnl/src/attr.c.

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

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

	nftnl_attr_payload_snprint(nftnl_attrbuf_data(attrbuf),
				   nftnl_attrbuf_len(attrbuf),
				   print_buf, PBUF_SIZE);
	printf("attrbuf = { %s }\n", print_buf);

	free (attrbuf);
	```

Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
---
 include/Makefile.am          |   1 +
 include/attr.h               |  29 ++++++
 include/libnftnl/Makefile.am |   1 +
 include/libnftnl/attr.h      |  68 ++++++++++++++
 src/Makefile.am              |   1 +
 src/attr.c                   | 208 +++++++++++++++++++++++++++++++++++++++++++
 src/libnftnl.map             |  18 ++++
 7 files changed, 326 insertions(+)
 create mode 100644 include/attr.h
 create mode 100644 include/libnftnl/attr.h
 create mode 100644 src/attr.c
diff mbox

Patch

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..8396211
--- /dev/null
+++ b/include/attr.h
@@ -0,0 +1,29 @@ 
+#ifndef _LIBNFTNL_ATTR_INTERNAL_H_
+#define _LIBNFTNL_ATTR_INTERNAL_H_
+
+#include <stdint.h>
+
+/*
+ * 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/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..e6e08f3
--- /dev/null
+++ b/include/libnftnl/attr.h
@@ -0,0 +1,68 @@ 
+#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 size);
+void nftnl_attrbuf_delete(struct nftnl_attrbuf *attrbuf);
+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_set_data(struct nftnl_attrbuf *attrbuf, const void *data,
+			    size_t len);
+struct nftnl_attr *nftnl_attrbuf_get_head(const struct nftnl_attrbuf *attrbuf);
+struct nftnl_attr *nftnl_attrbuf_get_tail(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,
+					size_t len, const void *data);
+
+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)
+
+/* 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 *)                          \
+	     nftnl_attr_get_value(nftnl_attrbuf_data(attrbuf));      \
+	     (char *)(nftnl_attrbuf_tail(attrbuf)) > (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);
+
+#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..b9938d5
--- /dev/null
+++ b/src/attr.c
@@ -0,0 +1,208 @@ 
+#include <libnftnl/attr.h>
+#include <attr.h>
+#include <utils.h>
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <ctype.h>
+
+
+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(nftnl_attrbuf_alloc);
+
+void nftnl_attrbuf_delete(struct nftnl_attrbuf *attrbuf)
+{
+	attrbuf->tail = (struct nftnl_attr *)attrbuf->data;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_delete);
+
+void nftnl_attrbuf_free(struct nftnl_attrbuf *attrbuf)
+{
+	nftnl_attrbuf_delete(attrbuf);
+	free((void *)attrbuf);
+}
+EXPORT_SYMBOL(nftnl_attrbuf_free);
+
+size_t nftnl_attrbuf_get_len(const struct nftnl_attrbuf *attrbuf)
+{
+	return (size_t)((char *)attrbuf->tail - (char *)attrbuf->data);
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_len);
+
+size_t nftnl_attrbuf_get_size(const struct nftnl_attrbuf *attrbuf)
+{
+	return (size_t)((char *)attrbuf->tail - (char *)attrbuf);
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_size);
+
+struct nftnl_attr *nftnl_attrbuf_get_head(const struct nftnl_attrbuf *attrbuf)
+{
+	return (struct nftnl_attr *)attrbuf->data;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_head);
+
+struct nftnl_attr *nftnl_attrbuf_get_tail(const struct nftnl_attrbuf *attrbuf)
+{
+	return attrbuf->tail;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_tail);
+
+void *nftnl_attrbuf_get_data(const struct nftnl_attrbuf *attrbuf)
+{
+	return (void *)attrbuf->data;
+}
+EXPORT_SYMBOL(nftnl_attrbuf_get_data);
+
+void nftnl_attrbuf_set_data(struct nftnl_attrbuf *attrbuf, const void *data,
+			    size_t len)
+{
+	memcpy(attrbuf->data, data, len);
+	attrbuf->tail = (struct nftnl_attr *)(attrbuf->data + len);
+}
+EXPORT_SYMBOL(nftnl_attrbuf_set_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);
+
+uint16_t nftnl_attr_get_size(const struct nftnl_attr *attr)
+{
+	return (char *)nftnl_attr_next(attr) - (char *)attr;
+}
+EXPORT_SYMBOL(nftnl_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(nftnl_attr_put);
+
+struct nftnl_attr *nftnl_attr_put_check(struct nftnl_attrbuf *attrbuf,
+					size_t bufsize, uint8_t type,
+					size_t len, const void *data)
+{
+	// Check if there is enough space
+	if (bufsize <
+		len +
+		sizeof(struct nftnl_attr) +
+		nftnl_attrbuf_get_len(attrbuf)
+	)
+		return NULL;
+
+	return nftnl_attr_put(attrbuf, type, len, data);
+}
+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);
+
+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);
+	}
+	if (boffset) {
+		/* delete last comma */
+		boffset--;
+		*(buf + boffset) = '\0';
+	}
+
+	return boffset;
+}
+EXPORT_SYMBOL(nftnl_attr_payload_snprint);
diff --git a/src/libnftnl.map b/src/libnftnl.map
index 2e193b7..e1396b9 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -336,6 +336,24 @@  global:
   nftnl_set_snprintf;
   nftnl_set_fprintf;
 
+  nftnl_attrbuf_alloc;
+  nftnl_attrbuf_delete;
+  nftnl_attrbuf_free;
+  nftnl_attrbuf_get_len;
+  nftnl_attrbuf_get_size;
+  nftnl_attrbuf_get_head;
+  nftnl_attrbuf_get_tail;
+  nftnl_attrbuf_get_data;
+  nftnl_attrbuf_set_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_next;
+  nftnl_attr_payload_snprint;
+
   nftnl_set_list_alloc;
   nftnl_set_list_free;
   nftnl_set_list_add;