* [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