* [PATCH 0/3] add object userdata and comment support
@ 2020-09-02 9:12 Jose M. Guisado Gomez
2020-09-02 9:12 ` [PATCH nf-next 1/3] netfilter: nf_tables: add userdata support for nft_object Jose M. Guisado Gomez
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Jose M. Guisado Gomez @ 2020-09-02 9:12 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
This patch series enables userdata for objects. Initially used to store
comments, can be extended for other use cases in the future.
There is a new API version for libnftnl as it did not export a necessary
function, nftnl_obj_get_data, to support getting object data.
nf-next:
netfilter: nf_tables: add userdata support for nft_object
include/net/netfilter/nf_tables.h | 2 ++
include/uapi/linux/netfilter/nf_tables.h | 2 ++
net/netfilter/nf_tables_api.c | 39 +++++++++++++++++++-----
3 files changed, 35 insertions(+), 8 deletions(-)
libnftnl:
object: add userdata and comment support
include/libnftnl/object.h | 1 +
include/libnftnl/udata.h | 6 ++++++
include/linux/netfilter/nf_tables.h | 2 ++
include/obj.h | 5 +++++
src/libnftnl.map | 4 ++++
src/object.c | 26 ++++++++++++++++++++++++++
6 files changed, 44 insertions(+)
nftables:
src: add comment support for objects
include/rule.h | 1 +
src/mnl.c | 12 +++++
src/netlink.c | 31 +++++++++++++
src/parser_bison.y | 40 +++++++++++++++++
src/rule.c | 20 +++++++++
.../testcases/optionals/comments_objects_0 | 44 +++++++++++++++++++
.../optionals/dumps/comments_objects_0.nft | 37 ++++++++++++++++
7 files changed, 185 insertions(+)
create mode 100755 tests/shell/testcases/optionals/comments_objects_0
create mode 100644 tests/shell/testcases/optionals/dumps/comments_objects_0.nft
--
2.27.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH nf-next 1/3] netfilter: nf_tables: add userdata support for nft_object
2020-09-02 9:12 [PATCH 0/3] add object userdata and comment support Jose M. Guisado Gomez
@ 2020-09-02 9:12 ` Jose M. Guisado Gomez
2020-09-08 10:42 ` Pablo Neira Ayuso
2020-09-02 9:12 ` [PATCH libnftnl 2/3] object: add userdata and comment support Jose M. Guisado Gomez
2020-09-02 9:12 ` [PATCH nftables 3/3] src: add comment support for objects Jose M. Guisado Gomez
2 siblings, 1 reply; 10+ messages in thread
From: Jose M. Guisado Gomez @ 2020-09-02 9:12 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Enables storing userdata for nft_object. Initially this will store an
optional comment but can be extended in the future as needed.
Adds new attribute NFTA_OBJ_USERDATA to nft_object.
Renames error labels in nf_tables_newobj to make it more clear.
Signed-off-by: Jose M. Guisado Gomez <guigom@riseup.net>
---
include/net/netfilter/nf_tables.h | 2 ++
include/uapi/linux/netfilter/nf_tables.h | 2 ++
net/netfilter/nf_tables_api.c | 39 +++++++++++++++++++-----
3 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 97a7e147a59a..99c1b3188b1e 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -1123,6 +1123,8 @@ struct nft_object {
u32 genmask:2,
use:30;
u64 handle;
+ u16 udlen;
+ u8 *udata;
/* runtime data below here */
const struct nft_object_ops *ops ____cacheline_aligned;
unsigned char data[]
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 543dc697b796..2a6e09dea1a0 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1559,6 +1559,7 @@ enum nft_ct_expectation_attributes {
* @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
* @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
* @NFTA_OBJ_HANDLE: object handle (NLA_U64)
+ * @NFTA_OBJ_USERDATA: user data (NLA_BINARY)
*/
enum nft_object_attributes {
NFTA_OBJ_UNSPEC,
@@ -1569,6 +1570,7 @@ enum nft_object_attributes {
NFTA_OBJ_USE,
NFTA_OBJ_HANDLE,
NFTA_OBJ_PAD,
+ NFTA_OBJ_USERDATA,
__NFTA_OBJ_MAX
};
#define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 6ccce2a2e715..55111aefd3db 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -5755,6 +5755,8 @@ static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
[NFTA_OBJ_TYPE] = { .type = NLA_U32 },
[NFTA_OBJ_DATA] = { .type = NLA_NESTED },
[NFTA_OBJ_HANDLE] = { .type = NLA_U64},
+ [NFTA_OBJ_USERDATA] = { .type = NLA_BINARY,
+ .len = NFT_USERDATA_MAXLEN },
};
static struct nft_object *nft_obj_init(const struct nft_ctx *ctx,
@@ -5901,6 +5903,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
struct nft_table *table;
struct nft_object *obj;
struct nft_ctx ctx;
+ u16 udlen = 0;
u32 objtype;
int err;
@@ -5946,7 +5949,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
obj = nft_obj_init(&ctx, type, nla[NFTA_OBJ_DATA]);
if (IS_ERR(obj)) {
err = PTR_ERR(obj);
- goto err1;
+ goto err_init;
}
obj->key.table = table;
obj->handle = nf_tables_alloc_handle(table);
@@ -5954,32 +5957,48 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
obj->key.name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
if (!obj->key.name) {
err = -ENOMEM;
- goto err2;
+ goto err_strdup;
+ }
+
+ if(nla[NFTA_OBJ_USERDATA]) {
+ udlen = nla_len(nla[NFTA_OBJ_USERDATA]);
+ obj->udata = kzalloc(udlen, GFP_KERNEL);
+ if (obj->udata == NULL)
+ goto err_userdata;
+ } else {
+ obj->udata = NULL;
+ }
+
+ if (udlen) {
+ nla_memcpy(obj->udata, nla[NFTA_OBJ_USERDATA], udlen);
+ obj->udlen = udlen;
}
err = nft_trans_obj_add(&ctx, NFT_MSG_NEWOBJ, obj);
if (err < 0)
- goto err3;
+ goto err_trans;
err = rhltable_insert(&nft_objname_ht, &obj->rhlhead,
nft_objname_ht_params);
if (err < 0)
- goto err4;
+ goto err_obj_ht;
list_add_tail_rcu(&obj->list, &table->objects);
table->use++;
return 0;
-err4:
+err_obj_ht:
/* queued in transaction log */
INIT_LIST_HEAD(&obj->list);
return err;
-err3:
+err_trans:
kfree(obj->key.name);
-err2:
+err_userdata:
+ kfree(obj->udata);
+err_strdup:
if (obj->ops->destroy)
obj->ops->destroy(&ctx, obj);
kfree(obj);
-err1:
+err_init:
module_put(type->owner);
return err;
}
@@ -6011,6 +6030,10 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
NFTA_OBJ_PAD))
goto nla_put_failure;
+ if (obj->udata &&
+ nla_put(skb, NFTA_OBJ_USERDATA, obj->udlen, obj->udata))
+ goto nla_put_failure;
+
nlmsg_end(skb, nlh);
return 0;
--
2.27.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH libnftnl 2/3] object: add userdata and comment support
2020-09-02 9:12 [PATCH 0/3] add object userdata and comment support Jose M. Guisado Gomez
2020-09-02 9:12 ` [PATCH nf-next 1/3] netfilter: nf_tables: add userdata support for nft_object Jose M. Guisado Gomez
@ 2020-09-02 9:12 ` Jose M. Guisado Gomez
2020-09-08 14:52 ` Pablo Neira Ayuso
2020-09-02 9:12 ` [PATCH nftables 3/3] src: add comment support for objects Jose M. Guisado Gomez
2 siblings, 1 reply; 10+ messages in thread
From: Jose M. Guisado Gomez @ 2020-09-02 9:12 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
This patch adds NFTNL_OBJ_USERDATA to support userdata for objects.
Also adds NFTNL_UDATA_OBJ_COMMENT to support comments for objects,
stored in userdata space.
Bumps libnftnl.map to 15 as nftnl_obj_get_data needs to be exported to
enable getting object attributes/data.
Signed-off-by: Jose M. Guisado Gomez <guigom@riseup.net>
---
include/libnftnl/object.h | 1 +
include/libnftnl/udata.h | 6 ++++++
include/linux/netfilter/nf_tables.h | 2 ++
include/obj.h | 5 +++++
src/libnftnl.map | 4 ++++
src/object.c | 26 ++++++++++++++++++++++++++
6 files changed, 44 insertions(+)
diff --git a/include/libnftnl/object.h b/include/libnftnl/object.h
index 4c23774..9bd83a5 100644
--- a/include/libnftnl/object.h
+++ b/include/libnftnl/object.h
@@ -19,6 +19,7 @@ enum {
NFTNL_OBJ_FAMILY,
NFTNL_OBJ_USE,
NFTNL_OBJ_HANDLE,
+ NFTNL_OBJ_USERDATA,
NFTNL_OBJ_BASE = 16,
__NFTNL_OBJ_MAX
};
diff --git a/include/libnftnl/udata.h b/include/libnftnl/udata.h
index ba6b3ab..2e38fcc 100644
--- a/include/libnftnl/udata.h
+++ b/include/libnftnl/udata.h
@@ -22,6 +22,12 @@ enum nftnl_udata_rule_types {
};
#define NFTNL_UDATA_RULE_MAX (__NFTNL_UDATA_RULE_MAX - 1)
+enum nftnl_udata_obj_types {
+ NFTNL_UDATA_OBJ_COMMENT,
+ __NFTNL_UDATA_OBJ_MAX
+};
+#define NFTNL_UDATA_OBJ_MAX (__NFTNL_UDATA_OBJ_MAX - 1)
+
#define NFTNL_UDATA_COMMENT_MAXLEN 128
enum nftnl_udata_set_types {
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index d508154..1d65ff9 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1542,6 +1542,7 @@ enum nft_ct_expectation_attributes {
* @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
* @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
* @NFTA_OBJ_HANDLE: object handle (NLA_U64)
+ * @NFTA_OBJ_HANDLE: user data (NLA_BINARY)
*/
enum nft_object_attributes {
NFTA_OBJ_UNSPEC,
@@ -1552,6 +1553,7 @@ enum nft_object_attributes {
NFTA_OBJ_USE,
NFTA_OBJ_HANDLE,
NFTA_OBJ_PAD,
+ NFTA_OBJ_USERDATA,
__NFTA_OBJ_MAX
};
#define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1)
diff --git a/include/obj.h b/include/obj.h
index 10f806c..d9e856a 100644
--- a/include/obj.h
+++ b/include/obj.h
@@ -22,6 +22,11 @@ struct nftnl_obj {
uint32_t flags;
uint64_t handle;
+ struct {
+ void *data;
+ uint32_t len;
+ } user;
+
union {
struct nftnl_obj_counter {
uint64_t pkts;
diff --git a/src/libnftnl.map b/src/libnftnl.map
index 6042479..ceafa3f 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -368,3 +368,7 @@ LIBNFTNL_14 {
nftnl_flowtable_set_array;
nftnl_flowtable_get_array;
} LIBNFTNL_13;
+
+LIBNFTNL_15 {
+ nftnl_obj_get_data;
+} LIBNFTNL_14;
diff --git a/src/object.c b/src/object.c
index 4f58272..008bade 100644
--- a/src/object.c
+++ b/src/object.c
@@ -57,6 +57,8 @@ void nftnl_obj_free(const struct nftnl_obj *obj)
xfree(obj->table);
if (obj->flags & (1 << NFTNL_OBJ_NAME))
xfree(obj->name);
+ if (obj->flags & (1 << NFTNL_OBJ_USERDATA))
+ xfree(obj->user.data);
xfree(obj);
}
@@ -103,6 +105,16 @@ void nftnl_obj_set_data(struct nftnl_obj *obj, uint16_t attr,
case NFTNL_OBJ_HANDLE:
memcpy(&obj->handle, data, sizeof(obj->handle));
break;
+ case NFTNL_OBJ_USERDATA:
+ if (obj->flags & (1 << NFTNL_OBJ_USERDATA))
+ xfree(obj->user.data);
+
+ obj->user.data = malloc(data_len);
+ if (!obj->user.data)
+ return;
+ memcpy(obj->user.data, data, data_len);
+ obj->user.len = data_len;
+ break;
default:
if (obj->ops)
obj->ops->set(obj, attr, data, data_len);
@@ -174,6 +186,9 @@ const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr,
case NFTNL_OBJ_HANDLE:
*data_len = sizeof(uint64_t);
return &obj->handle;
+ case NFTNL_OBJ_USERDATA:
+ *data_len = obj->user.len;
+ return obj->user.data;
default:
if (obj->ops)
return obj->ops->get(obj, attr, data_len);
@@ -235,6 +250,8 @@ void nftnl_obj_nlmsg_build_payload(struct nlmsghdr *nlh,
mnl_attr_put_u32(nlh, NFTA_OBJ_TYPE, htonl(obj->ops->type));
if (obj->flags & (1 << NFTNL_OBJ_HANDLE))
mnl_attr_put_u64(nlh, NFTA_OBJ_HANDLE, htobe64(obj->handle));
+ if (obj->flags & (1 << NFTNL_OBJ_USERDATA))
+ mnl_attr_put(nlh, NFTA_OBJ_USERDATA, obj->user.len, obj->user.data);
if (obj->ops) {
struct nlattr *nest = mnl_attr_nest_start(nlh, NFTA_OBJ_DATA);
@@ -269,6 +286,10 @@ static int nftnl_obj_parse_attr_cb(const struct nlattr *attr, void *data)
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
+ case NFTA_OBJ_USERDATA:
+ if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
+ abi_breakage();
+ break;
}
tb[type] = attr;
@@ -315,6 +336,11 @@ int nftnl_obj_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_obj *obj)
obj->handle = be64toh(mnl_attr_get_u64(tb[NFTA_OBJ_HANDLE]));
obj->flags |= (1 << NFTNL_OBJ_HANDLE);
}
+ if (tb[NFTA_OBJ_USERDATA]) {
+ nftnl_obj_set_data(obj, NFTNL_OBJ_USERDATA,
+ mnl_attr_get_payload(tb[NFTA_OBJ_USERDATA]),
+ mnl_attr_get_payload_len(tb[NFTA_OBJ_USERDATA]));
+ }
obj->family = nfg->nfgen_family;
obj->flags |= (1 << NFTNL_OBJ_FAMILY);
--
2.27.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH nftables 3/3] src: add comment support for objects
2020-09-02 9:12 [PATCH 0/3] add object userdata and comment support Jose M. Guisado Gomez
2020-09-02 9:12 ` [PATCH nf-next 1/3] netfilter: nf_tables: add userdata support for nft_object Jose M. Guisado Gomez
2020-09-02 9:12 ` [PATCH libnftnl 2/3] object: add userdata and comment support Jose M. Guisado Gomez
@ 2020-09-02 9:12 ` Jose M. Guisado Gomez
2020-09-03 9:16 ` [PATCH nftables 3/3, v2] " Jose M. Guisado Gomez
2020-09-08 14:53 ` [PATCH nftables 3/3] " Pablo Neira Ayuso
2 siblings, 2 replies; 10+ messages in thread
From: Jose M. Guisado Gomez @ 2020-09-02 9:12 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Enables specifying an optional comment when declaring named objects. The
comment is to be specified inside the object's block ({} block)
Relies on libnftnl exporting nftnl_obj_get_data and kernel space support
to store the comments.
For consistency, this patch makes the comment be printed first when
listing objects.
Adds a testcase importing all commented named objects except for secmark,
although it's supported.
Example: Adding a quota with a comment
> add table inet filter
> nft add quota inet filter q { over 1200 bytes \; comment "test_comment"\; }
> list ruleset
table inet filter {
quota q {
comment "test_comment"
over 1200 bytes
}
}
Signed-off-by: Jose M. Guisado Gomez <guigom@riseup.net>
---
include/rule.h | 1 +
src/mnl.c | 12 +++++
src/netlink.c | 31 +++++++++++++
src/parser_bison.y | 40 +++++++++++++++++
src/rule.c | 20 +++++++++
| 44 +++++++++++++++++++
| 37 ++++++++++++++++
7 files changed, 185 insertions(+)
create mode 100755 tests/shell/testcases/optionals/comments_objects_0
create mode 100644 tests/shell/testcases/optionals/dumps/comments_objects_0.nft
diff --git a/include/rule.h b/include/rule.h
index 56f1951f..837005b1 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -479,6 +479,7 @@ struct obj {
struct handle handle;
uint32_t type;
unsigned int refcnt;
+ const char *comment;
union {
struct counter counter;
struct quota quota;
diff --git a/src/mnl.c b/src/mnl.c
index cdcf9490..ca4f4b2a 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1189,6 +1189,7 @@ int mnl_nft_obj_add(struct netlink_ctx *ctx, struct cmd *cmd,
unsigned int flags)
{
struct obj *obj = cmd->object;
+ struct nftnl_udata_buf *udbuf;
struct nftnl_obj *nlo;
struct nlmsghdr *nlh;
@@ -1199,6 +1200,17 @@ int mnl_nft_obj_add(struct netlink_ctx *ctx, struct cmd *cmd,
nftnl_obj_set_u32(nlo, NFTNL_OBJ_FAMILY, cmd->handle.family);
nftnl_obj_set_u32(nlo, NFTNL_OBJ_TYPE, obj->type);
+ if (obj->comment) {
+ udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
+ if (!udbuf)
+ memory_allocation_error();
+ if (!nftnl_udata_put_strz(udbuf, NFTNL_UDATA_OBJ_COMMENT, obj->comment))
+ memory_allocation_error();
+ nftnl_obj_set_data(nlo, NFTNL_OBJ_USERDATA, nftnl_udata_buf_data(udbuf),
+ nftnl_udata_buf_len(udbuf));
+ nftnl_udata_buf_free(udbuf);
+ }
+
switch (obj->type) {
case NFT_OBJECT_COUNTER:
nftnl_obj_set_u64(nlo, NFTNL_OBJ_CTR_PKTS,
diff --git a/src/netlink.c b/src/netlink.c
index a107f492..6912b018 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1314,11 +1314,33 @@ void netlink_dump_obj(struct nftnl_obj *nln, struct netlink_ctx *ctx)
fprintf(fp, "\n");
}
+static int obj_parse_udata_cb(const struct nftnl_udata *attr, void *data)
+{
+ unsigned char *value = nftnl_udata_get(attr);
+ uint8_t type = nftnl_udata_type(attr);
+ const struct nftnl_udata **tb = data;
+ uint8_t len = nftnl_udata_len(attr);
+
+ switch (type) {
+ case NFTNL_UDATA_OBJ_COMMENT:
+ if (value[len - 1] != '\0')
+ return -1;
+ break;
+ default:
+ return 0;
+ }
+ tb[type] = attr;
+ return 0;
+}
+
struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
struct nftnl_obj *nlo)
{
+ const struct nftnl_udata *ud[NFTNL_UDATA_OBJ_MAX + 1] = {};
+ const char *udata;
struct obj *obj;
uint32_t type;
+ uint32_t ulen;
obj = obj_alloc(&netlink_location);
obj->handle.family = nftnl_obj_get_u32(nlo, NFTNL_OBJ_FAMILY);
@@ -1328,6 +1350,15 @@ struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
xstrdup(nftnl_obj_get_str(nlo, NFTNL_OBJ_NAME));
obj->handle.handle.id =
nftnl_obj_get_u64(nlo, NFTNL_OBJ_HANDLE);
+ if (nftnl_obj_is_set(nlo, NFTNL_OBJ_USERDATA)) {
+ udata = nftnl_obj_get_data(nlo, NFTNL_OBJ_USERDATA, &ulen);
+ if (nftnl_udata_parse(udata, ulen, obj_parse_udata_cb, ud) < 0) {
+ netlink_io_error(ctx, NULL, "Cannot parse userdata");
+ return NULL;
+ }
+ if (ud[NFTNL_UDATA_OBJ_COMMENT])
+ obj->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_OBJ_COMMENT]));
+ }
type = nftnl_obj_get_u32(nlo, NFTNL_OBJ_TYPE);
switch (type) {
diff --git a/src/parser_bison.y b/src/parser_bison.y
index d938f566..cf689426 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1006,10 +1006,18 @@ add_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_COUNTER, &$2, &@$, $3);
}
+ | COUNTER obj_spec counter_obj '{' counter_block '}'
+ {
+ $$ = cmd_alloc(CMD_ADD, CMD_OBJ_COUNTER, &$2, &@$, $3);
+ }
| QUOTA obj_spec quota_obj quota_config
{
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_QUOTA, &$2, &@$, $3);
}
+ | QUOTA obj_spec quota_obj '{' quota_block '}'
+ {
+ $$ = cmd_alloc(CMD_ADD, CMD_OBJ_QUOTA, &$2, &@$, $3);
+ }
| CT HELPER obj_spec ct_obj_alloc '{' ct_helper_block '}'
{
$$ = cmd_alloc_obj_ct(CMD_ADD, NFT_OBJECT_CT_HELPER, &$3, &@$, $4);
@@ -2039,6 +2047,10 @@ counter_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | counter_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
quota_block : /* empty */ { $$ = $<obj>-1; }
@@ -2048,6 +2060,10 @@ quota_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | quota_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
ct_helper_block : /* empty */ { $$ = $<obj>-1; }
@@ -2057,6 +2073,10 @@ ct_helper_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | ct_helper_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
ct_timeout_block : /*empty */
@@ -2070,6 +2090,10 @@ ct_timeout_block : /*empty */
{
$$ = $1;
}
+ | ct_timeout_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
ct_expect_block : /*empty */ { $$ = $<obj>-1; }
@@ -2079,6 +2103,10 @@ ct_expect_block : /*empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | ct_expect_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
limit_block : /* empty */ { $$ = $<obj>-1; }
@@ -2088,6 +2116,10 @@ limit_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | limit_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
secmark_block : /* empty */ { $$ = $<obj>-1; }
@@ -2097,6 +2129,10 @@ secmark_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | secmark_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
synproxy_block : /* empty */ { $$ = $<obj>-1; }
@@ -2106,6 +2142,10 @@ synproxy_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | synproxy_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
type_identifier : STRING { $$ = $1; }
diff --git a/src/rule.c b/src/rule.c
index 2c4b5dbe..4ebc8d81 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1893,6 +1893,7 @@ void obj_free(struct obj *obj)
{
if (--obj->refcnt > 0)
return;
+ xfree(obj->comment);
handle_free(&obj->handle);
xfree(obj);
}
@@ -1986,6 +1987,16 @@ static const char *synproxy_timestamp_to_str(const uint32_t flags)
return "";
}
+static void obj_print_comment(const struct obj *obj,
+ struct print_fmt_options *opts,
+ struct output_ctx *octx)
+{
+ if (obj->comment)
+ nft_print(octx, "%s%s%scomment \"%s\"",
+ opts->nl, opts->tab, opts->tab,
+ obj->comment);
+}
+
static void obj_print_data(const struct obj *obj,
struct print_fmt_options *opts,
struct output_ctx *octx)
@@ -1995,6 +2006,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
if (nft_output_stateless(octx)) {
nft_print(octx, "packets 0 bytes 0");
@@ -2010,6 +2022,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
data_unit = get_rate(obj->quota.bytes, &bytes);
nft_print(octx, "%s%" PRIu64 " %s",
@@ -2027,6 +2040,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
nft_print(octx, "\"%s\"%s", obj->secmark.ctx, opts->nl);
break;
@@ -2034,6 +2048,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s", opts->nl);
nft_print(octx, "%s%stype \"%s\" protocol ",
opts->tab, opts->tab, obj->ct_helper.name);
@@ -2048,6 +2063,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s", opts->nl);
nft_print(octx, "%s%sprotocol ", opts->tab, opts->tab);
print_proto_name_proto(obj->ct_timeout.l4proto, octx);
@@ -2063,6 +2079,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s", opts->nl);
nft_print(octx, "%s%sprotocol ", opts->tab, opts->tab);
print_proto_name_proto(obj->ct_expect.l4proto, octx);
@@ -2091,6 +2108,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
switch (obj->limit.type) {
case NFT_LIMIT_PKTS:
@@ -2128,6 +2146,8 @@ static void obj_print_data(const struct obj *obj,
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
+
if (flags & NF_SYNPROXY_OPT_MSS) {
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
nft_print(octx, "mss %u", obj->synproxy.mss);
--git a/tests/shell/testcases/optionals/comments_objects_0 b/tests/shell/testcases/optionals/comments_objects_0
new file mode 100755
index 00000000..7437c77b
--- /dev/null
+++ b/tests/shell/testcases/optionals/comments_objects_0
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+EXPECTED='table ip filter {
+ quota q {
+ over 1200 bytes
+ comment "test1"
+ }
+
+ counter c {
+ packets 0 bytes 0
+ comment "test2"
+ }
+
+ ct helper h {
+ type "sip" protocol tcp
+ l3proto ip
+ comment "test3"
+ }
+
+ ct expectation e {
+ protocol tcp
+ dport 666
+ timeout 100ms
+ size 96
+ l3proto ip
+ comment "test4"
+ }
+
+ limit l {
+ rate 400/hour
+ comment "test5"
+ }
+
+ synproxy s {
+ mss 1460
+ wscale 2
+ comment "test6"
+ }
+}
+'
+
+set -e
+
+$NFT -f - <<< "$EXPECTED"
--git a/tests/shell/testcases/optionals/dumps/comments_objects_0.nft b/tests/shell/testcases/optionals/dumps/comments_objects_0.nft
new file mode 100644
index 00000000..b760ced6
--- /dev/null
+++ b/tests/shell/testcases/optionals/dumps/comments_objects_0.nft
@@ -0,0 +1,37 @@
+table ip filter {
+ quota q {
+ comment "test1"
+ over 1200 bytes
+ }
+
+ counter c {
+ comment "test2"
+ packets 0 bytes 0
+ }
+
+ ct helper h {
+ comment "test3"
+ type "sip" protocol tcp
+ l3proto ip
+ }
+
+ ct expectation e {
+ comment "test4"
+ protocol tcp
+ dport 666
+ timeout 100ms
+ size 96
+ l3proto ip
+ }
+
+ limit l {
+ comment "test5"
+ rate 400/hour
+ }
+
+ synproxy s {
+ comment "test6"
+ mss 1460
+ wscale 2
+ }
+}
--
2.27.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH nftables 3/3, v2] src: add comment support for objects
2020-09-02 9:12 ` [PATCH nftables 3/3] src: add comment support for objects Jose M. Guisado Gomez
@ 2020-09-03 9:16 ` Jose M. Guisado Gomez
2020-09-08 14:53 ` [PATCH nftables 3/3] " Pablo Neira Ayuso
1 sibling, 0 replies; 10+ messages in thread
From: Jose M. Guisado Gomez @ 2020-09-03 9:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Enables specifying an optional comment when declaring named objects. The
comment is to be specified inside the object's block ({} block)
Relies on libnftnl exporting nftnl_obj_get_data and kernel space support
to store the comments.
For consistency, this patch makes the comment be printed first when
listing objects.
Adds a testcase importing all commented named objects except for secmark,
although it's supported.
Example: Adding a quota with a comment
> add table inet filter
> nft add quota inet filter q { over 1200 bytes \; comment "test_comment"\; }
> list ruleset
table inet filter {
quota q {
comment "test_comment"
over 1200 bytes
}
}
Signed-off-by: Jose M. Guisado Gomez <guigom@riseup.net>
---
Adds missing parser { *_block } for some objects in v1
include/rule.h | 1 +
src/mnl.c | 12 +++++
src/netlink.c | 31 +++++++++++
src/parser_bison.y | 52 +++++++++++++++++++
src/rule.c | 20 +++++++
| 44 ++++++++++++++++
| 37 +++++++++++++
7 files changed, 197 insertions(+)
create mode 100755 tests/shell/testcases/optionals/comments_objects_0
create mode 100644 tests/shell/testcases/optionals/dumps/comments_objects_0.nft
diff --git a/include/rule.h b/include/rule.h
index 56f1951f..837005b1 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -479,6 +479,7 @@ struct obj {
struct handle handle;
uint32_t type;
unsigned int refcnt;
+ const char *comment;
union {
struct counter counter;
struct quota quota;
diff --git a/src/mnl.c b/src/mnl.c
index cdcf9490..ca4f4b2a 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1189,6 +1189,7 @@ int mnl_nft_obj_add(struct netlink_ctx *ctx, struct cmd *cmd,
unsigned int flags)
{
struct obj *obj = cmd->object;
+ struct nftnl_udata_buf *udbuf;
struct nftnl_obj *nlo;
struct nlmsghdr *nlh;
@@ -1199,6 +1200,17 @@ int mnl_nft_obj_add(struct netlink_ctx *ctx, struct cmd *cmd,
nftnl_obj_set_u32(nlo, NFTNL_OBJ_FAMILY, cmd->handle.family);
nftnl_obj_set_u32(nlo, NFTNL_OBJ_TYPE, obj->type);
+ if (obj->comment) {
+ udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
+ if (!udbuf)
+ memory_allocation_error();
+ if (!nftnl_udata_put_strz(udbuf, NFTNL_UDATA_OBJ_COMMENT, obj->comment))
+ memory_allocation_error();
+ nftnl_obj_set_data(nlo, NFTNL_OBJ_USERDATA, nftnl_udata_buf_data(udbuf),
+ nftnl_udata_buf_len(udbuf));
+ nftnl_udata_buf_free(udbuf);
+ }
+
switch (obj->type) {
case NFT_OBJECT_COUNTER:
nftnl_obj_set_u64(nlo, NFTNL_OBJ_CTR_PKTS,
diff --git a/src/netlink.c b/src/netlink.c
index a107f492..6912b018 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1314,11 +1314,33 @@ void netlink_dump_obj(struct nftnl_obj *nln, struct netlink_ctx *ctx)
fprintf(fp, "\n");
}
+static int obj_parse_udata_cb(const struct nftnl_udata *attr, void *data)
+{
+ unsigned char *value = nftnl_udata_get(attr);
+ uint8_t type = nftnl_udata_type(attr);
+ const struct nftnl_udata **tb = data;
+ uint8_t len = nftnl_udata_len(attr);
+
+ switch (type) {
+ case NFTNL_UDATA_OBJ_COMMENT:
+ if (value[len - 1] != '\0')
+ return -1;
+ break;
+ default:
+ return 0;
+ }
+ tb[type] = attr;
+ return 0;
+}
+
struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
struct nftnl_obj *nlo)
{
+ const struct nftnl_udata *ud[NFTNL_UDATA_OBJ_MAX + 1] = {};
+ const char *udata;
struct obj *obj;
uint32_t type;
+ uint32_t ulen;
obj = obj_alloc(&netlink_location);
obj->handle.family = nftnl_obj_get_u32(nlo, NFTNL_OBJ_FAMILY);
@@ -1328,6 +1350,15 @@ struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
xstrdup(nftnl_obj_get_str(nlo, NFTNL_OBJ_NAME));
obj->handle.handle.id =
nftnl_obj_get_u64(nlo, NFTNL_OBJ_HANDLE);
+ if (nftnl_obj_is_set(nlo, NFTNL_OBJ_USERDATA)) {
+ udata = nftnl_obj_get_data(nlo, NFTNL_OBJ_USERDATA, &ulen);
+ if (nftnl_udata_parse(udata, ulen, obj_parse_udata_cb, ud) < 0) {
+ netlink_io_error(ctx, NULL, "Cannot parse userdata");
+ return NULL;
+ }
+ if (ud[NFTNL_UDATA_OBJ_COMMENT])
+ obj->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_OBJ_COMMENT]));
+ }
type = nftnl_obj_get_u32(nlo, NFTNL_OBJ_TYPE);
switch (type) {
diff --git a/src/parser_bison.y b/src/parser_bison.y
index d938f566..7242c4c3 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1006,10 +1006,18 @@ add_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_COUNTER, &$2, &@$, $3);
}
+ | COUNTER obj_spec counter_obj '{' counter_block '}'
+ {
+ $$ = cmd_alloc(CMD_ADD, CMD_OBJ_COUNTER, &$2, &@$, $3);
+ }
| QUOTA obj_spec quota_obj quota_config
{
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_QUOTA, &$2, &@$, $3);
}
+ | QUOTA obj_spec quota_obj '{' quota_block '}'
+ {
+ $$ = cmd_alloc(CMD_ADD, CMD_OBJ_QUOTA, &$2, &@$, $3);
+ }
| CT HELPER obj_spec ct_obj_alloc '{' ct_helper_block '}'
{
$$ = cmd_alloc_obj_ct(CMD_ADD, NFT_OBJECT_CT_HELPER, &$3, &@$, $4);
@@ -1026,14 +1034,26 @@ add_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_LIMIT, &$2, &@$, $3);
}
+ | LIMIT obj_spec limit_obj '{' limit_block '}'
+ {
+ $$ = cmd_alloc(CMD_ADD, CMD_OBJ_LIMIT, &$2, &@$, $3);
+ }
| SECMARK obj_spec secmark_obj secmark_config
{
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_SECMARK, &$2, &@$, $3);
}
+ | SECMARK obj_spec secmark_obj '{' secmark_block '}'
+ {
+ $$ = cmd_alloc(CMD_ADD, CMD_OBJ_SECMARK, &$2, &@$, $3);
+ }
| SYNPROXY obj_spec synproxy_obj synproxy_config
{
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_SYNPROXY, &$2, &@$, $3);
}
+ | SYNPROXY obj_spec synproxy_obj '{' synproxy_block '}'
+ {
+ $$ = cmd_alloc(CMD_ADD, CMD_OBJ_SYNPROXY, &$2, &@$, $3);
+ }
;
replace_cmd : RULE ruleid_spec rule
@@ -2039,6 +2059,10 @@ counter_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | counter_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
quota_block : /* empty */ { $$ = $<obj>-1; }
@@ -2048,6 +2072,10 @@ quota_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | quota_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
ct_helper_block : /* empty */ { $$ = $<obj>-1; }
@@ -2057,6 +2085,10 @@ ct_helper_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | ct_helper_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
ct_timeout_block : /*empty */
@@ -2070,6 +2102,10 @@ ct_timeout_block : /*empty */
{
$$ = $1;
}
+ | ct_timeout_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
ct_expect_block : /*empty */ { $$ = $<obj>-1; }
@@ -2079,6 +2115,10 @@ ct_expect_block : /*empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | ct_expect_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
limit_block : /* empty */ { $$ = $<obj>-1; }
@@ -2088,6 +2128,10 @@ limit_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | limit_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
secmark_block : /* empty */ { $$ = $<obj>-1; }
@@ -2097,6 +2141,10 @@ secmark_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | secmark_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
synproxy_block : /* empty */ { $$ = $<obj>-1; }
@@ -2106,6 +2154,10 @@ synproxy_block : /* empty */ { $$ = $<obj>-1; }
{
$$ = $1;
}
+ | synproxy_block comment_spec
+ {
+ $<obj>1->comment = $2;
+ }
;
type_identifier : STRING { $$ = $1; }
diff --git a/src/rule.c b/src/rule.c
index 2c4b5dbe..4ebc8d81 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1893,6 +1893,7 @@ void obj_free(struct obj *obj)
{
if (--obj->refcnt > 0)
return;
+ xfree(obj->comment);
handle_free(&obj->handle);
xfree(obj);
}
@@ -1986,6 +1987,16 @@ static const char *synproxy_timestamp_to_str(const uint32_t flags)
return "";
}
+static void obj_print_comment(const struct obj *obj,
+ struct print_fmt_options *opts,
+ struct output_ctx *octx)
+{
+ if (obj->comment)
+ nft_print(octx, "%s%s%scomment \"%s\"",
+ opts->nl, opts->tab, opts->tab,
+ obj->comment);
+}
+
static void obj_print_data(const struct obj *obj,
struct print_fmt_options *opts,
struct output_ctx *octx)
@@ -1995,6 +2006,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
if (nft_output_stateless(octx)) {
nft_print(octx, "packets 0 bytes 0");
@@ -2010,6 +2022,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
data_unit = get_rate(obj->quota.bytes, &bytes);
nft_print(octx, "%s%" PRIu64 " %s",
@@ -2027,6 +2040,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
nft_print(octx, "\"%s\"%s", obj->secmark.ctx, opts->nl);
break;
@@ -2034,6 +2048,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s", opts->nl);
nft_print(octx, "%s%stype \"%s\" protocol ",
opts->tab, opts->tab, obj->ct_helper.name);
@@ -2048,6 +2063,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s", opts->nl);
nft_print(octx, "%s%sprotocol ", opts->tab, opts->tab);
print_proto_name_proto(obj->ct_timeout.l4proto, octx);
@@ -2063,6 +2079,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s", opts->nl);
nft_print(octx, "%s%sprotocol ", opts->tab, opts->tab);
print_proto_name_proto(obj->ct_expect.l4proto, octx);
@@ -2091,6 +2108,7 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, " %s {", obj->handle.obj.name);
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
switch (obj->limit.type) {
case NFT_LIMIT_PKTS:
@@ -2128,6 +2146,8 @@ static void obj_print_data(const struct obj *obj,
if (nft_output_handle(octx))
nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ obj_print_comment(obj, opts, octx);
+
if (flags & NF_SYNPROXY_OPT_MSS) {
nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab);
nft_print(octx, "mss %u", obj->synproxy.mss);
--git a/tests/shell/testcases/optionals/comments_objects_0 b/tests/shell/testcases/optionals/comments_objects_0
new file mode 100755
index 00000000..7437c77b
--- /dev/null
+++ b/tests/shell/testcases/optionals/comments_objects_0
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+EXPECTED='table ip filter {
+ quota q {
+ over 1200 bytes
+ comment "test1"
+ }
+
+ counter c {
+ packets 0 bytes 0
+ comment "test2"
+ }
+
+ ct helper h {
+ type "sip" protocol tcp
+ l3proto ip
+ comment "test3"
+ }
+
+ ct expectation e {
+ protocol tcp
+ dport 666
+ timeout 100ms
+ size 96
+ l3proto ip
+ comment "test4"
+ }
+
+ limit l {
+ rate 400/hour
+ comment "test5"
+ }
+
+ synproxy s {
+ mss 1460
+ wscale 2
+ comment "test6"
+ }
+}
+'
+
+set -e
+
+$NFT -f - <<< "$EXPECTED"
--git a/tests/shell/testcases/optionals/dumps/comments_objects_0.nft b/tests/shell/testcases/optionals/dumps/comments_objects_0.nft
new file mode 100644
index 00000000..b760ced6
--- /dev/null
+++ b/tests/shell/testcases/optionals/dumps/comments_objects_0.nft
@@ -0,0 +1,37 @@
+table ip filter {
+ quota q {
+ comment "test1"
+ over 1200 bytes
+ }
+
+ counter c {
+ comment "test2"
+ packets 0 bytes 0
+ }
+
+ ct helper h {
+ comment "test3"
+ type "sip" protocol tcp
+ l3proto ip
+ }
+
+ ct expectation e {
+ comment "test4"
+ protocol tcp
+ dport 666
+ timeout 100ms
+ size 96
+ l3proto ip
+ }
+
+ limit l {
+ comment "test5"
+ rate 400/hour
+ }
+
+ synproxy s {
+ comment "test6"
+ mss 1460
+ wscale 2
+ }
+}
--
2.27.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH nf-next 1/3] netfilter: nf_tables: add userdata support for nft_object
2020-09-02 9:12 ` [PATCH nf-next 1/3] netfilter: nf_tables: add userdata support for nft_object Jose M. Guisado Gomez
@ 2020-09-08 10:42 ` Pablo Neira Ayuso
2020-09-08 11:01 ` [PATCH nf-next 1/3, v2] " Jose M. Guisado Gomez
0 siblings, 1 reply; 10+ messages in thread
From: Pablo Neira Ayuso @ 2020-09-08 10:42 UTC (permalink / raw)
To: Jose M. Guisado Gomez; +Cc: netfilter-devel
On Wed, Sep 02, 2020 at 11:12:39AM +0200, Jose M. Guisado Gomez wrote:
> diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
> index 6ccce2a2e715..55111aefd3db 100644
> --- a/net/netfilter/nf_tables_api.c
> +++ b/net/netfilter/nf_tables_api.c
[...]
> @@ -5954,32 +5957,48 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
> obj->key.name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
> if (!obj->key.name) {
> err = -ENOMEM;
> - goto err2;
> + goto err_strdup;
> + }
> +
> + if(nla[NFTA_OBJ_USERDATA]) {
> + udlen = nla_len(nla[NFTA_OBJ_USERDATA]);
> + obj->udata = kzalloc(udlen, GFP_KERNEL);
> + if (obj->udata == NULL)
> + goto err_userdata;
> + } else {
> + obj->udata = NULL;
> + }
> +
> + if (udlen) {
> + nla_memcpy(obj->udata, nla[NFTA_OBJ_USERDATA], udlen);
> + obj->udlen = udlen;
> }
Probably simplify this?
if(nla[NFTA_OBJ_USERDATA]) {
udlen = nla_len(nla[NFTA_OBJ_USERDATA]);
obj->udata = kzalloc(udlen, GFP_KERNEL);
if (obj->udata == NULL)
goto err_userdata;
nla_memcpy(obj->udata, nla[NFTA_OBJ_USERDATA], udlen);
obj->udlen = udlen;
}
obj is allocated via kzalloc(), so obj->udata is already guaranteed to
be initialized to NULL, no need for the 'else' side of the branch.
Thanks.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH nf-next 1/3, v2] netfilter: nf_tables: add userdata support for nft_object
2020-09-08 10:42 ` Pablo Neira Ayuso
@ 2020-09-08 11:01 ` Jose M. Guisado Gomez
2020-09-08 14:36 ` Pablo Neira Ayuso
0 siblings, 1 reply; 10+ messages in thread
From: Jose M. Guisado Gomez @ 2020-09-08 11:01 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Enables storing userdata for nft_object. Initially this will store an
optional comment but can be extended in the future as needed.
Adds new attribute NFTA_OBJ_USERDATA to nft_object.
Signed-off-by: Jose M. Guisado Gomez <guigom@riseup.net>
---
Simplifications from v1, as proposed.
include/net/netfilter/nf_tables.h | 2 ++
include/uapi/linux/netfilter/nf_tables.h | 2 ++
net/netfilter/nf_tables_api.c | 35 ++++++++++++++++++------
3 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 97a7e147a59a..99c1b3188b1e 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -1123,6 +1123,8 @@ struct nft_object {
u32 genmask:2,
use:30;
u64 handle;
+ u16 udlen;
+ u8 *udata;
/* runtime data below here */
const struct nft_object_ops *ops ____cacheline_aligned;
unsigned char data[]
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 543dc697b796..2a6e09dea1a0 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1559,6 +1559,7 @@ enum nft_ct_expectation_attributes {
* @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
* @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
* @NFTA_OBJ_HANDLE: object handle (NLA_U64)
+ * @NFTA_OBJ_USERDATA: user data (NLA_BINARY)
*/
enum nft_object_attributes {
NFTA_OBJ_UNSPEC,
@@ -1569,6 +1570,7 @@ enum nft_object_attributes {
NFTA_OBJ_USE,
NFTA_OBJ_HANDLE,
NFTA_OBJ_PAD,
+ NFTA_OBJ_USERDATA,
__NFTA_OBJ_MAX
};
#define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 6ccce2a2e715..7d6cd49c246e 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -5755,6 +5755,8 @@ static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
[NFTA_OBJ_TYPE] = { .type = NLA_U32 },
[NFTA_OBJ_DATA] = { .type = NLA_NESTED },
[NFTA_OBJ_HANDLE] = { .type = NLA_U64},
+ [NFTA_OBJ_USERDATA] = { .type = NLA_BINARY,
+ .len = NFT_USERDATA_MAXLEN },
};
static struct nft_object *nft_obj_init(const struct nft_ctx *ctx,
@@ -5901,6 +5903,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
struct nft_table *table;
struct nft_object *obj;
struct nft_ctx ctx;
+ u16 udlen = 0;
u32 objtype;
int err;
@@ -5946,7 +5949,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
obj = nft_obj_init(&ctx, type, nla[NFTA_OBJ_DATA]);
if (IS_ERR(obj)) {
err = PTR_ERR(obj);
- goto err1;
+ goto err_init;
}
obj->key.table = table;
obj->handle = nf_tables_alloc_handle(table);
@@ -5954,32 +5957,44 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
obj->key.name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
if (!obj->key.name) {
err = -ENOMEM;
- goto err2;
+ goto err_strdup;
+ }
+
+ if(nla[NFTA_OBJ_USERDATA]) {
+ udlen = nla_len(nla[NFTA_OBJ_USERDATA]);
+ obj->udata = kzalloc(udlen, GFP_KERNEL);
+ if (obj->udata == NULL)
+ goto err_userdata;
+
+ nla_memcpy(obj->udata, nla[NFTA_OBJ_USERDATA], udlen);
+ obj->udlen = udlen;
}
err = nft_trans_obj_add(&ctx, NFT_MSG_NEWOBJ, obj);
if (err < 0)
- goto err3;
+ goto err_trans;
err = rhltable_insert(&nft_objname_ht, &obj->rhlhead,
nft_objname_ht_params);
if (err < 0)
- goto err4;
+ goto err_obj_ht;
list_add_tail_rcu(&obj->list, &table->objects);
table->use++;
return 0;
-err4:
+err_obj_ht:
/* queued in transaction log */
INIT_LIST_HEAD(&obj->list);
return err;
-err3:
+err_trans:
kfree(obj->key.name);
-err2:
+err_userdata:
+ kfree(obj->udata);
+err_strdup:
if (obj->ops->destroy)
obj->ops->destroy(&ctx, obj);
kfree(obj);
-err1:
+err_init:
module_put(type->owner);
return err;
}
@@ -6011,6 +6026,10 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
NFTA_OBJ_PAD))
goto nla_put_failure;
+ if (obj->udata &&
+ nla_put(skb, NFTA_OBJ_USERDATA, obj->udlen, obj->udata))
+ goto nla_put_failure;
+
nlmsg_end(skb, nlh);
return 0;
--
2.27.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH nf-next 1/3, v2] netfilter: nf_tables: add userdata support for nft_object
2020-09-08 11:01 ` [PATCH nf-next 1/3, v2] " Jose M. Guisado Gomez
@ 2020-09-08 14:36 ` Pablo Neira Ayuso
0 siblings, 0 replies; 10+ messages in thread
From: Pablo Neira Ayuso @ 2020-09-08 14:36 UTC (permalink / raw)
To: Jose M. Guisado Gomez; +Cc: netfilter-devel
On Tue, Sep 08, 2020 at 01:01:41PM +0200, Jose M. Guisado Gomez wrote:
> Enables storing userdata for nft_object. Initially this will store an
> optional comment but can be extended in the future as needed.
>
> Adds new attribute NFTA_OBJ_USERDATA to nft_object.
Applied, thanks.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH libnftnl 2/3] object: add userdata and comment support
2020-09-02 9:12 ` [PATCH libnftnl 2/3] object: add userdata and comment support Jose M. Guisado Gomez
@ 2020-09-08 14:52 ` Pablo Neira Ayuso
0 siblings, 0 replies; 10+ messages in thread
From: Pablo Neira Ayuso @ 2020-09-08 14:52 UTC (permalink / raw)
To: Jose M. Guisado Gomez; +Cc: netfilter-devel
On Wed, Sep 02, 2020 at 11:12:40AM +0200, Jose M. Guisado Gomez wrote:
> This patch adds NFTNL_OBJ_USERDATA to support userdata for objects.
>
> Also adds NFTNL_UDATA_OBJ_COMMENT to support comments for objects,
> stored in userdata space.
>
> Bumps libnftnl.map to 15 as nftnl_obj_get_data needs to be exported to
> enable getting object attributes/data.
Applied, thanks.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH nftables 3/3] src: add comment support for objects
2020-09-02 9:12 ` [PATCH nftables 3/3] src: add comment support for objects Jose M. Guisado Gomez
2020-09-03 9:16 ` [PATCH nftables 3/3, v2] " Jose M. Guisado Gomez
@ 2020-09-08 14:53 ` Pablo Neira Ayuso
1 sibling, 0 replies; 10+ messages in thread
From: Pablo Neira Ayuso @ 2020-09-08 14:53 UTC (permalink / raw)
To: Jose M. Guisado Gomez; +Cc: netfilter-devel
On Wed, Sep 02, 2020 at 11:12:41AM +0200, Jose M. Guisado Gomez wrote:
> Enables specifying an optional comment when declaring named objects. The
> comment is to be specified inside the object's block ({} block)
>
> Relies on libnftnl exporting nftnl_obj_get_data and kernel space support
> to store the comments.
>
> For consistency, this patch makes the comment be printed first when
> listing objects.
>
> Adds a testcase importing all commented named objects except for secmark,
> although it's supported.
>
> Example: Adding a quota with a comment
>
> > add table inet filter
> > nft add quota inet filter q { over 1200 bytes \; comment "test_comment"\; }
> > list ruleset
>
> table inet filter {
> quota q {
> comment "test_comment"
> over 1200 bytes
> }
> }
Also applied, thanks.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2020-09-08 20:08 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-02 9:12 [PATCH 0/3] add object userdata and comment support Jose M. Guisado Gomez
2020-09-02 9:12 ` [PATCH nf-next 1/3] netfilter: nf_tables: add userdata support for nft_object Jose M. Guisado Gomez
2020-09-08 10:42 ` Pablo Neira Ayuso
2020-09-08 11:01 ` [PATCH nf-next 1/3, v2] " Jose M. Guisado Gomez
2020-09-08 14:36 ` Pablo Neira Ayuso
2020-09-02 9:12 ` [PATCH libnftnl 2/3] object: add userdata and comment support Jose M. Guisado Gomez
2020-09-08 14:52 ` Pablo Neira Ayuso
2020-09-02 9:12 ` [PATCH nftables 3/3] src: add comment support for objects Jose M. Guisado Gomez
2020-09-03 9:16 ` [PATCH nftables 3/3, v2] " Jose M. Guisado Gomez
2020-09-08 14:53 ` [PATCH nftables 3/3] " Pablo Neira Ayuso
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).