From patchwork Fri May 21 11:39:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Westphal X-Patchwork-Id: 1482171 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Fml5C03jGz9sVt for ; Fri, 21 May 2021 21:39:43 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233128AbhEULlE (ORCPT ); Fri, 21 May 2021 07:41:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59528 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233001AbhEULk6 (ORCPT ); Fri, 21 May 2021 07:40:58 -0400 Received: from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc [IPv6:2a0a:51c0:0:12e:520::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7455CC061763 for ; Fri, 21 May 2021 04:39:34 -0700 (PDT) Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.92) (envelope-from ) id 1lk3V6-0005W9-U0; Fri, 21 May 2021 13:39:32 +0200 From: Florian Westphal To: Cc: Florian Westphal Subject: [PATCH nf-next 1/4] netfilter: nf_tables: allow to dump all registered base hooks Date: Fri, 21 May 2021 13:39:19 +0200 Message-Id: <20210521113922.20798-2-fw@strlen.de> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210521113922.20798-1-fw@strlen.de> References: <20210521113922.20798-1-fw@strlen.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This dumps the active hook pipeline to userspace. Userspace needs to pass the address family and the hook point. For the netdev family/ingress hook, a device name must be provided as well. This allows 'nft' to display the priority of each hook. Example: family ip hook prerouting { -0000000300 -0000000150 -0000000100 } ... so this shows 3 active hooks with -300/-150/-100. With manual work this is enough to figure out which hooks these are. Followup patch will include the hook and module name (if any). Signed-off-by: Florian Westphal Reported-by: kernel test robot --- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_queue.c | 4 +- net/netfilter/nf_tables_api.c | 216 +++++++++++++++++++++++ 3 files changed, 219 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 19715e2679d1..5810e41eff33 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -124,6 +124,7 @@ enum nf_tables_msg_types { NFT_MSG_NEWFLOWTABLE, NFT_MSG_GETFLOWTABLE, NFT_MSG_DELFLOWTABLE, + NFT_MSG_GETNFHOOKS, NFT_MSG_MAX, }; diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index bbd1209694b8..224238b20825 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -259,7 +259,7 @@ static unsigned int nf_iterate(struct sk_buff *skb, return NF_ACCEPT; } -static struct nf_hook_entries *nf_hook_entries_head(const struct net *net, u8 pf, u8 hooknum) +static struct nf_hook_entries *nf_queue_hook_entries_head(const struct net *net, u8 pf, u8 hooknum) { switch (pf) { #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE @@ -292,7 +292,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) net = entry->state.net; pf = entry->state.pf; - hooks = nf_hook_entries_head(net, pf, entry->state.hook); + hooks = nf_queue_hook_entries_head(net, pf, entry->state.hook); i = entry->hook_index; if (WARN_ON_ONCE(!hooks || i >= hooks->num_hook_entries)) { diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index d63d2d8f769c..2bfa80e93658 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -7911,6 +7911,216 @@ static int nf_tables_getgen(struct sk_buff *skb, const struct nfnl_info *info, return err; } +static const struct nf_hook_entries * +nf_hook_entries_head(u8 pf, unsigned int hook, struct net *net, const char *dev) +{ + const struct nf_hook_entries *hook_head = NULL; + struct net_device *netdev; + + switch (pf) { + case NFPROTO_IPV4: + if (hook >= ARRAY_SIZE(net->nf.hooks_ipv4)) + return ERR_PTR(-EINVAL); + hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]); + break; + case NFPROTO_IPV6: + hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]); + if (hook >= ARRAY_SIZE(net->nf.hooks_ipv6)) + return ERR_PTR(-EINVAL); + break; + case NFPROTO_ARP: +#ifdef CONFIG_NETFILTER_FAMILY_ARP + if (hook >= ARRAY_SIZE(net->nf.hooks_arp)) + return ERR_PTR(-EINVAL); + hook_head = rcu_dereference(net->nf.hooks_arp[hook]); +#endif + break; + case NFPROTO_BRIDGE: +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE + if (hook >= ARRAY_SIZE(net->nf.hooks_bridge)) + return ERR_PTR(-EINVAL); + hook_head = rcu_dereference(net->nf.hooks_bridge[hook]); +#endif + break; +#if IS_ENABLED(CONFIG_DECNET) + case NFPROTO_DECNET: + if (hook >= ARRAY_SIZE(net->nf.hooks_decnet)) + return ERR_PTR(-EINVAL); + hook_head = rcu_dereference(net->nf.hooks_decnet[hook]); + break; +#endif +#ifdef CONFIG_NETFILTER_INGRESS + case NFPROTO_NETDEV: + if (hook != NF_NETDEV_INGRESS) + return ERR_PTR(-EOPNOTSUPP); + + if (!dev) + return ERR_PTR(-ENODEV); + + netdev = dev_get_by_name_rcu(net, dev); + if (!netdev) + return ERR_PTR(-ENODEV); + + return rcu_dereference(netdev->nf_hooks_ingress); +#endif + default: + return ERR_PTR(-EPROTONOSUPPORT); + } + + return hook_head; +} + +struct nft_dump_hooks_data { + char devname[IFNAMSIZ]; + unsigned long headv; + unsigned int seq; + u8 hook; +}; + +static int nf_tables_dump_one_hook(struct sk_buff *nlskb, + const struct nft_dump_hooks_data *ctx, + const struct nf_hook_ops *ops) +{ + unsigned int portid = NETLINK_CB(nlskb).portid; + struct net *net = sock_net(nlskb->sk); + struct nlmsghdr *nlh; + int ret; + + nlh = nfnl_msg_put(nlskb, portid, ctx->seq, NFT_MSG_GETNFHOOKS, + NLM_F_MULTI, ops->pf, NFNETLINK_V0, nft_base_seq(net)); + if (!nlh) + goto nla_put_failure; + + ret = nla_put_be32(nlskb, NFTA_HOOK_HOOKNUM, htonl(ops->hooknum)); + if (ret) + goto nla_put_failure; + + ret = nla_put_be32(nlskb, NFTA_HOOK_PRIORITY, htonl(ops->priority)); + if (ret) + goto nla_put_failure; + + nlmsg_end(nlskb, nlh); + return 0; +nla_put_failure: + nlmsg_trim(nlskb, nlh); + return ret; +} + +static int nf_tables_dump_basehooks(struct sk_buff *nlskb, + struct netlink_callback *cb) +{ + struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); + struct nft_dump_hooks_data *ctx = cb->data; + int err, family = nfmsg->nfgen_family; + struct net *net = sock_net(nlskb->sk); + struct nf_hook_ops * const *ops; + const struct nf_hook_entries *e; + unsigned int i = cb->args[0]; + + rcu_read_lock(); + cb->seq = ctx->seq; + + e = nf_hook_entries_head(family, ctx->hook, net, ctx->devname); + if (!e) + goto done; + + if (IS_ERR(e)) { + ctx->seq++; + goto done; + } + + if ((unsigned long)e != ctx->headv || i >= e->num_hook_entries) + ctx->seq++; + + ops = nf_hook_entries_get_hook_ops(e); + + for (; i < e->num_hook_entries; i++) { + err = nf_tables_dump_one_hook(nlskb, ctx, ops[i]); + if (err) + break; + } + +done: + nl_dump_check_consistent(cb, nlmsg_hdr(nlskb)); + rcu_read_unlock(); + cb->args[0] = i; + return nlskb->len; +} + +static int nf_tables_dump_basehooks_start(struct netlink_callback *cb) +{ + const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); + const struct nlattr * const *nla = cb->data; + struct nft_dump_hooks_data *ctx = NULL; + struct net *net = sock_net(cb->skb->sk); + u8 family = nfmsg->nfgen_family; + char name[IFNAMSIZ] = ""; + const void *head; + u32 hooknum; + + hooknum = ntohl(nla_get_be32(nla[NFTA_HOOK_HOOKNUM])); + if (hooknum > 255) + return -EINVAL; + + if (family == NFPROTO_NETDEV) { + if (!nla[NFTA_HOOK_DEV]) + return -EINVAL; + + nla_strscpy(name, nla[NFTA_HOOK_DEV], sizeof(name)); + } + + rcu_read_lock(); + /* Not dereferenced; for consistency check only */ + head = nf_hook_entries_head(family, hooknum, net, name); + rcu_read_unlock(); + + if (head && IS_ERR(head)) + return PTR_ERR(head); + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->headv = (unsigned long)head; + + ctx->hook = hooknum; + strscpy(ctx->devname, name, sizeof(ctx->devname)); + cb->data = ctx; + cb->seq = 1; + return 0; +} + +static int nf_tables_dump_basehooks_stop(struct netlink_callback *cb) +{ + kfree(cb->data); + return 0; +} + +static int nft_get_basehooks(struct sk_buff *skb, + const struct nfnl_info *info, + const struct nlattr * const nla[]) +{ + if (!nla[NFTA_HOOK_HOOKNUM]) + return -EINVAL; + + if (ntohl(nla_get_be32(nla[NFTA_HOOK_HOOKNUM])) > 255) + return -EINVAL; + + if (info->nlh->nlmsg_flags & NLM_F_DUMP) { + struct netlink_dump_control c = { + .start = nf_tables_dump_basehooks_start, + .done = nf_tables_dump_basehooks_stop, + .dump = nf_tables_dump_basehooks, + .module = THIS_MODULE, + .data = (void *)nla, + }; + + return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c); + } + + return -EOPNOTSUPP; +} + static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { [NFT_MSG_NEWTABLE] = { .call = nf_tables_newtable, @@ -8048,6 +8258,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .attr_count = NFTA_FLOWTABLE_MAX, .policy = nft_flowtable_policy, }, + [NFT_MSG_GETNFHOOKS] = { + .call = nft_get_basehooks, + .type = NFNL_CB_RCU, + .attr_count = NFTA_HOOK_MAX, + .policy = nft_hook_policy, + }, }; static int nf_tables_validate(struct net *net) From patchwork Fri May 21 11:39:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Westphal X-Patchwork-Id: 1482172 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Fml5C2ddKz9sV5 for ; Fri, 21 May 2021 21:39:43 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233946AbhEULlE (ORCPT ); Fri, 21 May 2021 07:41:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59542 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233846AbhEULlC (ORCPT ); Fri, 21 May 2021 07:41:02 -0400 Received: from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc [IPv6:2a0a:51c0:0:12e:520::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 05EC2C061574 for ; Fri, 21 May 2021 04:39:39 -0700 (PDT) Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.92) (envelope-from ) id 1lk3VB-0005WI-5J; Fri, 21 May 2021 13:39:37 +0200 From: Florian Westphal To: Cc: Florian Westphal Subject: [PATCH nf-next 2/4] netfilter: nf_tables: include function and module name in hook dumps Date: Fri, 21 May 2021 13:39:20 +0200 Message-Id: <20210521113922.20798-3-fw@strlen.de> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210521113922.20798-1-fw@strlen.de> References: <20210521113922.20798-1-fw@strlen.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org If KALLSYMS are available, include the hook function name and the module name that registered the hook. This avoids need to manually annotate all existing hooks. Example output: family ip hook prerouting { -0000000300 iptable_raw_hook [iptable_raw] -0000000150 iptable_mangle_hook [iptable_mangle] -0000000100 nf_nat_ipv4_pre_routing [nf_nat] } Signed-off-by: Florian Westphal --- include/linux/netfilter.h | 4 ++++ include/uapi/linux/netfilter/nf_tables.h | 4 ++++ net/netfilter/core.c | 6 ++++++ net/netfilter/nf_tables_api.c | 13 +++++++++++++ 4 files changed, 27 insertions(+) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index f0f3a8354c3c..63f77794f5ed 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -195,6 +195,10 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state, void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state, const struct nf_hook_entries *e); + +bool nf_get_hook_info(const struct nf_hook_ops *ops, + char fn[KSYM_NAME_LEN], char **module_name); + /** * nf_hook - call a netfilter hook * diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 5810e41eff33..ba6545a32e34 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -147,6 +147,8 @@ enum nft_list_attributes { * @NFTA_HOOK_PRIORITY: netfilter hook priority (NLA_U32) * @NFTA_HOOK_DEV: netdevice name (NLA_STRING) * @NFTA_HOOK_DEVS: list of netdevices (NLA_NESTED) + * @NFTA_HOOK_FUNCTION_NAME: hook function name (NLA_STRING) + * @NFTA_HOOK_MODULE_NAME: kernel module that registered this hook (NLA_STRING) */ enum nft_hook_attributes { NFTA_HOOK_UNSPEC, @@ -154,6 +156,8 @@ enum nft_hook_attributes { NFTA_HOOK_PRIORITY, NFTA_HOOK_DEV, NFTA_HOOK_DEVS, + NFTA_HOOK_FUNCTION_NAME, + NFTA_HOOK_MODULE_NAME, __NFTA_HOOK_MAX }; #define NFTA_HOOK_MAX (__NFTA_HOOK_MAX - 1) diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 63d032191e62..d14715c568c8 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -749,6 +749,12 @@ static struct pernet_operations netfilter_net_ops = { .exit = netfilter_net_exit, }; +bool nf_get_hook_info(const struct nf_hook_ops *ops, char fn[KSYM_NAME_LEN], char **modname) +{ + return kallsyms_lookup((unsigned long)ops->hook, NULL, NULL, modname, fn); +} +EXPORT_SYMBOL_GPL(nf_get_hook_info); + int __init netfilter_init(void) { int ret; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 2bfa80e93658..216f2921be0f 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -7983,6 +7983,7 @@ static int nf_tables_dump_one_hook(struct sk_buff *nlskb, { unsigned int portid = NETLINK_CB(nlskb).portid; struct net *net = sock_net(nlskb->sk); + char *module_name, fn[KSYM_NAME_LEN]; struct nlmsghdr *nlh; int ret; @@ -7991,6 +7992,18 @@ static int nf_tables_dump_one_hook(struct sk_buff *nlskb, if (!nlh) goto nla_put_failure; + if (nf_get_hook_info(ops, fn, &module_name)) { + ret = nla_put_string(nlskb, NFTA_HOOK_FUNCTION_NAME, fn); + if (ret) + goto nla_put_failure; + + if (module_name) { + ret = nla_put_string(nlskb, NFTA_HOOK_MODULE_NAME, module_name); + if (ret) + goto nla_put_failure; + } + } + ret = nla_put_be32(nlskb, NFTA_HOOK_HOOKNUM, htonl(ops->hooknum)); if (ret) goto nla_put_failure; From patchwork Fri May 21 11:39:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Westphal X-Patchwork-Id: 1482173 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Fml5H1rKdz9sV5 for ; Fri, 21 May 2021 21:39:47 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234623AbhEULlH (ORCPT ); Fri, 21 May 2021 07:41:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59556 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234155AbhEULlG (ORCPT ); Fri, 21 May 2021 07:41:06 -0400 Received: from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc [IPv6:2a0a:51c0:0:12e:520::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DFE31C061574 for ; Fri, 21 May 2021 04:39:42 -0700 (PDT) Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.92) (envelope-from ) id 1lk3VF-0005WR-Es; Fri, 21 May 2021 13:39:41 +0200 From: Florian Westphal To: Cc: Florian Westphal Subject: [PATCH nf-next 3/4] netfilter: annotate nf_tables base hook ops Date: Fri, 21 May 2021 13:39:21 +0200 Message-Id: <20210521113922.20798-4-fw@strlen.de> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210521113922.20798-1-fw@strlen.de> References: <20210521113922.20798-1-fw@strlen.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This will allow a followup patch to treat the 'ops->priv' pointer as nft_chain argument without having to first walk to table/chains for a match. Signed-off-by: Florian Westphal --- include/linux/netfilter.h | 8 +++++++- net/netfilter/nf_tables_api.c | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 63f77794f5ed..6c327689ff82 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -77,12 +77,18 @@ struct nf_hook_state { typedef unsigned int nf_hookfn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state); +enum nf_hook_ops_type { + NF_HOOK_OP_UNDEFINED, + NF_HOOK_OP_NF_TABLES, +}; + struct nf_hook_ops { /* User fills in from here down. */ nf_hookfn *hook; struct net_device *dev; void *priv; - u_int8_t pf; + u8 pf; + enum nf_hook_ops_type hook_ops_type:8; unsigned int hooknum; /* Hooks are ordered in ascending priority. */ int priority; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 216f2921be0f..935f46db16bb 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -2172,8 +2172,10 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, } nft_trans_chain_policy(trans) = NFT_CHAIN_POLICY_UNSET; - if (nft_is_base_chain(chain)) + if (nft_is_base_chain(chain)) { + basechain->ops.hook_ops_type = NF_HOOK_OP_NF_TABLES; nft_trans_chain_policy(trans) = policy; + } err = nft_chain_add(table, chain); if (err < 0) { From patchwork Fri May 21 11:39:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Westphal X-Patchwork-Id: 1482174 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Fml5L14j0z9sVt for ; Fri, 21 May 2021 21:39:50 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234730AbhEULlM (ORCPT ); Fri, 21 May 2021 07:41:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59576 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234235AbhEULlK (ORCPT ); Fri, 21 May 2021 07:41:10 -0400 Received: from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc [IPv6:2a0a:51c0:0:12e:520::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 12CFFC061574 for ; Fri, 21 May 2021 04:39:47 -0700 (PDT) Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.92) (envelope-from ) id 1lk3VJ-0005Wt-Jg; Fri, 21 May 2021 13:39:45 +0200 From: Florian Westphal To: Cc: Florian Westphal Subject: [PATCH nf-next 4/4] netfilter: nf_tables: include table and chain name when dumping hooks Date: Fri, 21 May 2021 13:39:22 +0200 Message-Id: <20210521113922.20798-5-fw@strlen.de> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210521113922.20798-1-fw@strlen.de> References: <20210521113922.20798-1-fw@strlen.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org For ip(6)tables, the function names will show 'raw', 'mangle', and so on, but for nf_tables the interpreter name is identical for all base chains in the same family, so its not easy to line up the defined chains with the hook function name. To make it easier to see how the ruleset lines up with the defined hooks, extend the hook dump to include the chain+table name. Example list: family ip hook input { -0000000150 iptable_mangle_hook [iptable_mangle] +0000000000 nft_do_chain_inet [nf_tables] # nft table filter chain input [..] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Florian Westphal --- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nf_tables_api.c | 42 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index ba6545a32e34..4822a837250d 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -149,6 +149,7 @@ enum nft_list_attributes { * @NFTA_HOOK_DEVS: list of netdevices (NLA_NESTED) * @NFTA_HOOK_FUNCTION_NAME: hook function name (NLA_STRING) * @NFTA_HOOK_MODULE_NAME: kernel module that registered this hook (NLA_STRING) + * @NFTA_HOOK_NFT_CHAIN_INFO: nft chain and table name (NLA_NESTED) */ enum nft_hook_attributes { NFTA_HOOK_UNSPEC, @@ -158,6 +159,7 @@ enum nft_hook_attributes { NFTA_HOOK_DEVS, NFTA_HOOK_FUNCTION_NAME, NFTA_HOOK_MODULE_NAME, + NFTA_HOOK_NFT_CHAIN_INFO, __NFTA_HOOK_MAX }; #define NFTA_HOOK_MAX (__NFTA_HOOK_MAX - 1) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 935f46db16bb..832531e457c6 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -7979,6 +7979,44 @@ struct nft_dump_hooks_data { u8 hook; }; +static int nla_put_chain_hook_info(struct sk_buff *nlskb, const struct nft_dump_hooks_data *ctx, + const struct nf_hook_ops *ops) +{ + struct net *net = sock_net(nlskb->sk); + struct nft_chain *chain; + struct nlattr *nest; + int ret = 0; + + if (ops->hook_ops_type != NF_HOOK_OP_NF_TABLES) + return 0; + + chain = ops->priv; + + if (WARN_ON_ONCE(!chain)) + return 0; + + if (!nft_is_active(net, chain)) + return 0; + + nest = nla_nest_start(nlskb, NFTA_HOOK_NFT_CHAIN_INFO); + if (!nest) + return -EMSGSIZE; + + ret = nla_put_string(nlskb, NFTA_CHAIN_TABLE, chain->table->name); + if (ret) { + nla_nest_cancel(nlskb, nest); + return -EMSGSIZE; + } + + ret = nla_put_string(nlskb, NFTA_CHAIN_NAME, chain->name); + if (ret) + nla_nest_cancel(nlskb, nest); + else + nla_nest_end(nlskb, nest); + + return ret; +} + static int nf_tables_dump_one_hook(struct sk_buff *nlskb, const struct nft_dump_hooks_data *ctx, const struct nf_hook_ops *ops) @@ -8014,6 +8052,10 @@ static int nf_tables_dump_one_hook(struct sk_buff *nlskb, if (ret) goto nla_put_failure; + ret = nla_put_chain_hook_info(nlskb, ctx, ops); + if (ret) + goto nla_put_failure; + nlmsg_end(nlskb, nlh); return 0; nla_put_failure: