From: Patrick McHardy <kaber@xxxxxxxxx> Add a chain handle as an alternative way to identify a chain for renames. The handle is constant, while the name might change. Kill the NFTA_CHAIN_NEW_NAME attribute since netlink attributes are supposed to be symetrical. Also fix netlink notification to not send a DELCHAIN/NEWCHAIN message for renames but a simple NEWCHAIN with the old handle and the new name. Signed-off-by: Patrick McHardy <kaber@xxxxxxxxx> --- include/linux/netfilter/nf_tables.h | 2 +- include/net/netfilter/nf_tables.h | 2 + net/netfilter/nf_tables_api.c | 100 ++++++++++++++++-------------------- 3 Dateien geändert, 48 Zeilen hinzugefügt(+), 56 Zeilen entfernt(-) diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index 5a6eefe..7640290 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -75,11 +75,11 @@ enum nft_table_attributes { enum nft_chain_attributes { NFTA_CHAIN_UNSPEC, NFTA_CHAIN_TABLE, + NFTA_CHAIN_HANDLE, NFTA_CHAIN_NAME, NFTA_CHAIN_HOOK, NFTA_CHAIN_POLICY, NFTA_CHAIN_USE, - NFTA_CHAIN_NEW_NAME, NFTA_CHAIN_TYPE, __NFTA_CHAIN_MAX }; diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index d1a8e9e..e7dc1da 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -346,6 +346,7 @@ enum nft_chain_flags { * * @rules: list of rules in the chain * @list: used internally + * @handle: chain handle * @flags: bitmask of enum nft_chain_flags * @use: number of jump references to this chain * @level: length of longest path to this chain @@ -354,6 +355,7 @@ enum nft_chain_flags { struct nft_chain { struct list_head rules; struct list_head list; + u64 handle; u8 flags; u16 use; u16 level; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 4b36b0a..bc4eb76 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -118,6 +118,11 @@ static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi, return ERR_PTR(-ENOENT); } +static inline u64 nf_tables_alloc_handle(struct nft_table *table) +{ + return ++table->hgenerator; +} + static struct nf_chain_type *chain_type[AF_MAX][NFT_CHAIN_T_MAX]; static int __nf_tables_chain_type_lookup(int family, const struct nlattr *nla) @@ -474,6 +479,19 @@ EXPORT_SYMBOL_GPL(nft_unregister_chain_type); * Chains */ +static struct nft_chain * +nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle) +{ + struct nft_chain *chain; + + list_for_each_entry(chain, &table->chains, list) { + if (chain->handle == handle) + return chain; + } + + return ERR_PTR(-ENOENT); +} + static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table, const struct nlattr *nla) { @@ -491,13 +509,12 @@ static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table, } static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = { + [NFTA_CHAIN_HANDLE] = { .type = NLA_U64 }, [NFTA_CHAIN_NAME] = { .type = NLA_STRING, .len = NFT_CHAIN_MAXNAMELEN - 1 }, [NFTA_CHAIN_TABLE] = { .type = NLA_STRING }, [NFTA_CHAIN_HOOK] = { .type = NLA_NESTED }, [NFTA_CHAIN_POLICY] = { .type = NLA_U32 }, - [NFTA_CHAIN_NEW_NAME] = { .type = NLA_STRING, - .len = NFT_CHAIN_MAXNAMELEN - 1 }, [NFTA_CHAIN_TYPE] = { .type = NLA_NUL_STRING }, }; @@ -527,6 +544,8 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, u32 portid, u32 seq, if (nla_put_string(skb, NFTA_CHAIN_TABLE, table->name)) goto nla_put_failure; + if (nla_put_be64(skb, NFTA_CHAIN_HANDLE, cpu_to_be64(chain->handle))) + goto nla_put_failure; if (nla_put_string(skb, NFTA_CHAIN_NAME, chain->name)) goto nla_put_failure; @@ -701,58 +720,19 @@ nf_tables_chain_policy(struct nft_base_chain *chain, const struct nlattr *attr) return 0; } -static int nf_tables_mvchain(struct sk_buff *skb, const struct nlmsghdr *nlh, - struct nft_table *table, - struct nft_chain *chain, - const struct nlattr * const nla[]) -{ - const struct nfgenmsg *nfmsg = nlmsg_data(nlh); - int family = nfmsg->nfgen_family; - struct nft_chain *new_chain; - struct nft_chain old_chain; - - if (!nla[NFTA_CHAIN_NEW_NAME]) - return -EINVAL; - - if (chain->flags & NFT_BASE_CHAIN) - return -EOPNOTSUPP; - - new_chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NEW_NAME]); - if (IS_ERR(new_chain)) { - if (PTR_ERR(new_chain) != -ENOENT) - return PTR_ERR(new_chain); - new_chain = NULL; - } - - if (new_chain != NULL) - return -EEXIST; - - new_chain = chain; - - nla_strlcpy(old_chain.name, - nla[NFTA_CHAIN_NAME], NFT_CHAIN_MAXNAMELEN); - nla_strlcpy(new_chain->name, - nla[NFTA_CHAIN_NEW_NAME], NFT_CHAIN_MAXNAMELEN); - - nf_tables_chain_notify(skb, nlh, table, &old_chain, NFT_MSG_DELCHAIN, - family); - nf_tables_chain_notify(skb, nlh, table, new_chain, NFT_MSG_NEWCHAIN, - family); - return 0; -} - static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[]) { const struct nfgenmsg *nfmsg = nlmsg_data(nlh); - const struct nlattr *name; + const struct nlattr * uninitialized_var(name); const struct nft_af_info *afi; struct nft_table *table; struct nft_chain *chain; struct nft_base_chain *basechain = NULL; struct nlattr *ha[NFTA_HOOK_MAX + 1]; int family = nfmsg->nfgen_family; + u64 handle = 0; int err; bool create; @@ -766,28 +746,42 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, if (IS_ERR(table)) return PTR_ERR(table); - name = nla[NFTA_CHAIN_NAME]; - chain = nf_tables_chain_lookup(table, name); - if (IS_ERR(chain)) { - if (PTR_ERR(chain) != -ENOENT) + chain = NULL; + if (nla[NFTA_CHAIN_HANDLE]) { + handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); + chain = nf_tables_chain_lookup_byhandle(table, handle); + if (IS_ERR(chain)) return PTR_ERR(chain); - chain = NULL; + } else { + name = nla[NFTA_CHAIN_NAME]; + chain = nf_tables_chain_lookup(table, name); + if (IS_ERR(chain)) { + if (PTR_ERR(chain) != -ENOENT) + return PTR_ERR(chain); + chain = NULL; + } } if (chain != NULL) { if (nlh->nlmsg_flags & NLM_F_EXCL) return -EEXIST; if (nlh->nlmsg_flags & NLM_F_REPLACE) - return nf_tables_mvchain(skb, nlh, table, chain, nla); + return -EOPNOTSUPP; if (nla[NFTA_CHAIN_POLICY]) { if (!(chain->flags & NFT_BASE_CHAIN)) return -EOPNOTSUPP; + err = nf_tables_chain_policy(nft_base_chain(chain), nla[NFTA_CHAIN_POLICY]); if (err < 0) return err; } + + if (nla[NFTA_CHAIN_HANDLE] && nla[NFTA_CHAIN_NAME]) + nla_strlcpy(chain->name, nla[NFTA_CHAIN_NAME], + NFT_CHAIN_MAXNAMELEN); + goto notify; } @@ -856,6 +850,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, } INIT_LIST_HEAD(&chain->rules); + chain->handle = nf_tables_alloc_handle(table); nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN); list_add_tail(&chain->list, &table->chains); @@ -1122,11 +1117,6 @@ static struct nft_rule *nf_tables_rule_lookup(const struct nft_chain *chain, return __nf_tables_rule_lookup(chain, be64_to_cpu(nla_get_be64(nla))); } -static inline u64 nf_tables_rule_alloc_handle(struct nft_table *table) -{ - return ++table->hgenerator; -} - static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_TABLE] = { .type = NLA_STRING }, [NFTA_RULE_CHAIN] = { .type = NLA_STRING, @@ -1389,7 +1379,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, return 0; } } else - handle = nf_tables_rule_alloc_handle(table); + handle = nf_tables_alloc_handle(table); if (handle == 0) return -EINVAL; -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html