Commit 5e948466 authored by Eric Leblond's avatar Eric Leblond Committed by Pablo Neira Ayuso

netfilter: nf_tables: add insert operation

This patch adds a new rule attribute NFTA_RULE_POSITION which is
used to store the position of a rule relatively to the others.
By providing the create command and specifying the position, the
rule is inserted after the rule with the handle equal to the
provided position.

Regarding notification, the position attribute specifies the
handle of the previous rule to make sure we don't point to any
stale rule in notifications coming from the commit path.

This patch includes the following fix from Pablo:

* nf_tables: fix rule deletion event reporting
Signed-off-by: default avatarEric Leblond <eric@regit.org>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 99633ab2
...@@ -153,6 +153,7 @@ enum nft_chain_attributes { ...@@ -153,6 +153,7 @@ enum nft_chain_attributes {
* @NFTA_RULE_HANDLE: numeric handle of the rule (NLA_U64) * @NFTA_RULE_HANDLE: numeric handle of the rule (NLA_U64)
* @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)
*/ */
enum nft_rule_attributes { enum nft_rule_attributes {
NFTA_RULE_UNSPEC, NFTA_RULE_UNSPEC,
...@@ -161,6 +162,7 @@ enum nft_rule_attributes { ...@@ -161,6 +162,7 @@ enum nft_rule_attributes {
NFTA_RULE_HANDLE, NFTA_RULE_HANDLE,
NFTA_RULE_EXPRESSIONS, NFTA_RULE_EXPRESSIONS,
NFTA_RULE_COMPAT, NFTA_RULE_COMPAT,
NFTA_RULE_POSITION,
__NFTA_RULE_MAX __NFTA_RULE_MAX
}; };
#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1) #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
......
...@@ -1273,6 +1273,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { ...@@ -1273,6 +1273,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
[NFTA_RULE_HANDLE] = { .type = NLA_U64 }, [NFTA_RULE_HANDLE] = { .type = NLA_U64 },
[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 },
}; };
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,
...@@ -1285,9 +1286,10 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, ...@@ -1285,9 +1286,10 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
struct nfgenmsg *nfmsg; struct nfgenmsg *nfmsg;
const struct nft_expr *expr, *next; const struct nft_expr *expr, *next;
struct nlattr *list; struct nlattr *list;
const struct nft_rule *prule;
int type = event | NFNL_SUBSYS_NFTABLES << 8;
event |= NFNL_SUBSYS_NFTABLES << 8; nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg),
nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
flags); flags);
if (nlh == NULL) if (nlh == NULL)
goto nla_put_failure; goto nla_put_failure;
...@@ -1304,6 +1306,13 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, ...@@ -1304,6 +1306,13 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
if (nla_put_be64(skb, NFTA_RULE_HANDLE, cpu_to_be64(rule->handle))) if (nla_put_be64(skb, NFTA_RULE_HANDLE, cpu_to_be64(rule->handle)))
goto nla_put_failure; goto nla_put_failure;
if ((event != NFT_MSG_DELRULE) && (rule->list.prev != &chain->rules)) {
prule = list_entry(rule->list.prev, struct nft_rule, list);
if (nla_put_be64(skb, NFTA_RULE_POSITION,
cpu_to_be64(prule->handle)))
goto nla_put_failure;
}
list = nla_nest_start(skb, NFTA_RULE_EXPRESSIONS); list = nla_nest_start(skb, NFTA_RULE_EXPRESSIONS);
if (list == NULL) if (list == NULL)
goto nla_put_failure; goto nla_put_failure;
...@@ -1499,7 +1508,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, ...@@ -1499,7 +1508,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
unsigned int size, i, n; unsigned int size, i, n;
int err, rem; int err, rem;
bool create; bool create;
u64 handle; u64 handle, pos_handle;
create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
...@@ -1533,6 +1542,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, ...@@ -1533,6 +1542,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
handle = nf_tables_alloc_handle(table); handle = nf_tables_alloc_handle(table);
} }
if (nla[NFTA_RULE_POSITION]) {
if (!(nlh->nlmsg_flags & NLM_F_CREATE))
return -EOPNOTSUPP;
pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
old_rule = __nf_tables_rule_lookup(chain, pos_handle);
if (IS_ERR(old_rule))
return PTR_ERR(old_rule);
}
nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
n = 0; n = 0;
...@@ -1573,9 +1592,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, ...@@ -1573,9 +1592,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
list_replace_rcu(&old_rule->list, &rule->list); list_replace_rcu(&old_rule->list, &rule->list);
nf_tables_rule_destroy(old_rule); nf_tables_rule_destroy(old_rule);
} else if (nlh->nlmsg_flags & NLM_F_APPEND) } else if (nlh->nlmsg_flags & NLM_F_APPEND)
list_add_tail_rcu(&rule->list, &chain->rules); if (old_rule)
else list_add_rcu(&rule->list, &old_rule->list);
list_add_rcu(&rule->list, &chain->rules); else
list_add_tail_rcu(&rule->list, &chain->rules);
else {
if (old_rule)
list_add_tail_rcu(&rule->list, &old_rule->list);
else
list_add_rcu(&rule->list, &chain->rules);
}
nf_tables_rule_notify(skb, nlh, table, chain, rule, NFT_MSG_NEWRULE, nf_tables_rule_notify(skb, nlh, table, chain, rule, NFT_MSG_NEWRULE,
nlh->nlmsg_flags & (NLM_F_APPEND | NLM_F_REPLACE), nlh->nlmsg_flags & (NLM_F_APPEND | NLM_F_REPLACE),
......
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