netfilter: nf_tables: add NFTA_RULE_ID attribute
This new attribute allows us to uniquely identify a rule in transaction. Robots may trigger an insertion followed by deletion in a batch, in that scenario we still don't have a public rule handle that we can use to delete the rule. This is similar to the NFTA_SET_ID attribute that allows us to refer to an anonymous set from a batch. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
74e8bcd21c
commit
1a94e38d25
|
@ -1202,10 +1202,13 @@ struct nft_trans {
|
|||
|
||||
struct nft_trans_rule {
|
||||
struct nft_rule *rule;
|
||||
u32 rule_id;
|
||||
};
|
||||
|
||||
#define nft_trans_rule(trans) \
|
||||
(((struct nft_trans_rule *)trans->data)->rule)
|
||||
#define nft_trans_rule_id(trans) \
|
||||
(((struct nft_trans_rule *)trans->data)->rule_id)
|
||||
|
||||
struct nft_trans_set {
|
||||
struct nft_set *set;
|
||||
|
|
|
@ -207,6 +207,7 @@ enum nft_chain_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_USERDATA: user data (NLA_BINARY, NFT_USERDATA_MAXLEN)
|
||||
* @NFTA_RULE_ID: uniquely identifies a rule in a transaction (NLA_U32)
|
||||
*/
|
||||
enum nft_rule_attributes {
|
||||
NFTA_RULE_UNSPEC,
|
||||
|
@ -218,6 +219,7 @@ enum nft_rule_attributes {
|
|||
NFTA_RULE_POSITION,
|
||||
NFTA_RULE_USERDATA,
|
||||
NFTA_RULE_PAD,
|
||||
NFTA_RULE_ID,
|
||||
__NFTA_RULE_MAX
|
||||
};
|
||||
#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
|
||||
|
|
|
@ -240,6 +240,10 @@ static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type,
|
|||
if (trans == NULL)
|
||||
return NULL;
|
||||
|
||||
if (msg_type == NFT_MSG_NEWRULE && ctx->nla[NFTA_RULE_ID] != NULL) {
|
||||
nft_trans_rule_id(trans) =
|
||||
ntohl(nla_get_be32(ctx->nla[NFTA_RULE_ID]));
|
||||
}
|
||||
nft_trans_rule(trans) = rule;
|
||||
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
||||
|
||||
|
@ -2293,6 +2297,22 @@ err1:
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
|
||||
const struct nlattr *nla)
|
||||
{
|
||||
u32 id = ntohl(nla_get_be32(nla));
|
||||
struct nft_trans *trans;
|
||||
|
||||
list_for_each_entry(trans, &net->nft.commit_list, list) {
|
||||
struct nft_rule *rule = nft_trans_rule(trans);
|
||||
|
||||
if (trans->msg_type == NFT_MSG_NEWRULE &&
|
||||
id == nft_trans_rule_id(trans))
|
||||
return rule;
|
||||
}
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
static int nf_tables_delrule(struct net *net, struct sock *nlsk,
|
||||
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
||||
const struct nlattr * const nla[])
|
||||
|
@ -2330,6 +2350,12 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
|
|||
if (IS_ERR(rule))
|
||||
return PTR_ERR(rule);
|
||||
|
||||
err = nft_delrule(&ctx, rule);
|
||||
} else if (nla[NFTA_RULE_ID]) {
|
||||
rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_ID]);
|
||||
if (IS_ERR(rule))
|
||||
return PTR_ERR(rule);
|
||||
|
||||
err = nft_delrule(&ctx, rule);
|
||||
} else {
|
||||
err = nft_delrule_by_chain(&ctx);
|
||||
|
|
Loading…
Reference in a new issue