Commit 0768b3b3 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: nf_tables: add optional user data area to rules

This allows us to store user comment strings, but it could be also
used to store any kind of information that the user application needs
to link to the rule.

Scratch 8 bits for the new ulen field that indicates the length the
user data area. 4 bits from the handle (so it's 42 bits long, according
to Patrick, it would last 139 years with 1000 new rules per second)
and 4 bits from dlen (so the expression data area is 4K, which seems
sufficient by now even considering the compatibility layer).
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Acked-by: default avatarPatrick McHardy <kaber@trash.net>
parent 39111fd2
...@@ -326,13 +326,15 @@ static inline void *nft_expr_priv(const struct nft_expr *expr) ...@@ -326,13 +326,15 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
* @handle: rule handle * @handle: rule handle
* @genmask: generation mask * @genmask: generation mask
* @dlen: length of expression data * @dlen: length of expression data
* @ulen: length of user data (used for comments)
* @data: expression data * @data: expression data
*/ */
struct nft_rule { struct nft_rule {
struct list_head list; struct list_head list;
u64 handle:46, u64 handle:42,
genmask:2, genmask:2,
dlen:16; dlen:12,
ulen:8;
unsigned char data[] unsigned char data[]
__attribute__((aligned(__alignof__(struct nft_expr)))); __attribute__((aligned(__alignof__(struct nft_expr))));
}; };
...@@ -371,6 +373,11 @@ static inline struct nft_expr *nft_expr_last(const struct nft_rule *rule) ...@@ -371,6 +373,11 @@ static inline struct nft_expr *nft_expr_last(const struct nft_rule *rule)
return (struct nft_expr *)&rule->data[rule->dlen]; return (struct nft_expr *)&rule->data[rule->dlen];
} }
static inline void *nft_userdata(const struct nft_rule *rule)
{
return (void *)&rule->data[rule->dlen];
}
/* /*
* The last pointer isn't really necessary, but the compiler isn't able to * The last pointer isn't really necessary, but the compiler isn't able to
* determine that the result of nft_expr_last() is always the same since it * determine that the result of nft_expr_last() is always the same since it
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _LINUX_NF_TABLES_H #define _LINUX_NF_TABLES_H
#define NFT_CHAIN_MAXNAMELEN 32 #define NFT_CHAIN_MAXNAMELEN 32
#define NFT_USERDATA_MAXLEN 256
enum nft_registers { enum nft_registers {
NFT_REG_VERDICT, NFT_REG_VERDICT,
...@@ -156,6 +157,7 @@ enum nft_chain_attributes { ...@@ -156,6 +157,7 @@ enum nft_chain_attributes {
* @NFTA_RULE_EXPRESSIONS: list of expressions (NLA_NESTED: nft_expr_attributes) * @NFTA_RULE_EXPRESSIONS: list of expressions (NLA_NESTED: nft_expr_attributes)
* @NFTA_RULE_COMPAT: compatibility specifications of the rule (NLA_NESTED: nft_rule_compat_attributes) * @NFTA_RULE_COMPAT: compatibility specifications of the rule (NLA_NESTED: nft_rule_compat_attributes)
* @NFTA_RULE_POSITION: numeric handle of the previous rule (NLA_U64) * @NFTA_RULE_POSITION: numeric handle of the previous rule (NLA_U64)
* @NFTA_RULE_USERDATA: user data (NLA_BINARY, NFT_USERDATA_MAXLEN)
*/ */
enum nft_rule_attributes { enum nft_rule_attributes {
NFTA_RULE_UNSPEC, NFTA_RULE_UNSPEC,
...@@ -165,6 +167,7 @@ enum nft_rule_attributes { ...@@ -165,6 +167,7 @@ enum nft_rule_attributes {
NFTA_RULE_EXPRESSIONS, NFTA_RULE_EXPRESSIONS,
NFTA_RULE_COMPAT, NFTA_RULE_COMPAT,
NFTA_RULE_POSITION, NFTA_RULE_POSITION,
NFTA_RULE_USERDATA,
__NFTA_RULE_MAX __NFTA_RULE_MAX
}; };
#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1) #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
......
...@@ -1295,6 +1295,8 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { ...@@ -1295,6 +1295,8 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
[NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED },
[NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED },
[NFTA_RULE_POSITION] = { .type = NLA_U64 }, [NFTA_RULE_POSITION] = { .type = NLA_U64 },
[NFTA_RULE_USERDATA] = { .type = NLA_BINARY,
.len = NFT_USERDATA_MAXLEN },
}; };
static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
...@@ -1347,6 +1349,10 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, ...@@ -1347,6 +1349,10 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
} }
nla_nest_end(skb, list); nla_nest_end(skb, list);
if (rule->ulen &&
nla_put(skb, NFTA_RULE_USERDATA, rule->ulen, nft_userdata(rule)))
goto nla_put_failure;
return nlmsg_end(skb, nlh); return nlmsg_end(skb, nlh);
nla_put_failure: nla_put_failure:
...@@ -1583,7 +1589,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, ...@@ -1583,7 +1589,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
struct nft_expr *expr; struct nft_expr *expr;
struct nft_ctx ctx; struct nft_ctx ctx;
struct nlattr *tmp; struct nlattr *tmp;
unsigned int size, i, n; unsigned int size, i, n, ulen = 0;
int err, rem; int err, rem;
bool create; bool create;
u64 handle, pos_handle; u64 handle, pos_handle;
...@@ -1649,8 +1655,11 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, ...@@ -1649,8 +1655,11 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
} }
} }
if (nla[NFTA_RULE_USERDATA])
ulen = nla_len(nla[NFTA_RULE_USERDATA]);
err = -ENOMEM; err = -ENOMEM;
rule = kzalloc(sizeof(*rule) + size, GFP_KERNEL); rule = kzalloc(sizeof(*rule) + size + ulen, GFP_KERNEL);
if (rule == NULL) if (rule == NULL)
goto err1; goto err1;
...@@ -1658,6 +1667,10 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, ...@@ -1658,6 +1667,10 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
rule->handle = handle; rule->handle = handle;
rule->dlen = size; rule->dlen = size;
rule->ulen = ulen;
if (ulen)
nla_memcpy(nft_userdata(rule), nla[NFTA_RULE_USERDATA], ulen);
expr = nft_expr_first(rule); expr = nft_expr_first(rule);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment