From: "Carlos Falgueras García" <carlosfg@riseup.net>
To: netfilter-devel@vger.kernel.org
Cc: pablo@netfilter.org, kaber@trash.net
Subject: [PATCH] libnftnl: Implement new buffer of TLV objects.
Date: Sat, 20 Feb 2016 23:43:52 +0100 [thread overview]
Message-ID: <1456008234-26845-1-git-send-email-carlosfg@riseup.net> (raw)
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
next reply other threads:[~2016-02-20 22:44 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-20 22:43 Carlos Falgueras García [this message]
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
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=1456008234-26845-1-git-send-email-carlosfg@riseup.net \
--to=carlosfg@riseup.net \
--cc=kaber@trash.net \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.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 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).