From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Tue, 30 Jun 2020 19:21:16 +0200
Subject: netfilter: nf_tables: add NFTA_RULE_CHAIN_ID attribute
Patch-mainline: v5.9-rc1
Git-commit: 837830a4b439bfeb86c70b0115c280377c84714b
References: bsc#1176447
This new netlink attribute allows you to add rules to chains by the
chain ID.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
include/uapi/linux/netfilter/nf_tables.h | 1
net/netfilter/nf_tables_api.c | 36 +++++++++++++++++++++++++++----
2 files changed, 33 insertions(+), 4 deletions(-)
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -240,6 +240,7 @@ enum nft_rule_attributes {
NFTA_RULE_PAD,
NFTA_RULE_ID,
NFTA_RULE_POSITION_ID,
+ NFTA_RULE_CHAIN_ID,
__NFTA_RULE_MAX
};
#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2164,6 +2164,22 @@ err:
return err;
}
+static struct nft_chain *nft_chain_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_chain *chain = trans->ctx.chain;
+
+ if (trans->msg_type == NFT_MSG_NEWCHAIN &&
+ id == nft_trans_chain_id(trans))
+ return chain;
+ }
+ return ERR_PTR(-ENOENT);
+}
+
static int nf_tables_newchain(struct net *net, struct sock *nlsk,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const nla[],
@@ -2644,6 +2660,7 @@ static const struct nla_policy nft_rule_
.len = NFT_USERDATA_MAXLEN },
[NFTA_RULE_ID] = { .type = NLA_U32 },
[NFTA_RULE_POSITION_ID] = { .type = NLA_U32 },
+ [NFTA_RULE_CHAIN_ID] = { .type = NLA_U32 },
};
static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
@@ -3062,10 +3079,21 @@ static int nf_tables_newrule(struct net
return PTR_ERR(table);
}
- chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN], genmask);
- if (IS_ERR(chain)) {
- NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
- return PTR_ERR(chain);
+ if (nla[NFTA_RULE_CHAIN]) {
+ chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN],
+ genmask);
+ if (IS_ERR(chain)) {
+ NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
+ return PTR_ERR(chain);
+ }
+ } else if (nla[NFTA_RULE_CHAIN_ID]) {
+ chain = nft_chain_lookup_byid(net, nla[NFTA_RULE_CHAIN_ID]);
+ if (IS_ERR(chain)) {
+ NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN_ID]);
+ return PTR_ERR(chain);
+ }
+ } else {
+ return -EINVAL;
}
if (nla[NFTA_RULE_HANDLE]) {