netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org
Subject: [PATCH 16/29] netfilter: nf_tables: introduce nft_chain_parse_hook()
Date: Mon,  5 Sep 2016 12:58:31 +0200	[thread overview]
Message-ID: <1473073124-5015-17-git-send-email-pablo@netfilter.org> (raw)
In-Reply-To: <1473073124-5015-1-git-send-email-pablo@netfilter.org>

Introduce a new function to wrap the code that parses the chain hook
configuration so we can reuse this code to validate chain updates.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nf_tables_api.c | 152 +++++++++++++++++++++++++-----------------
 1 file changed, 89 insertions(+), 63 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 7e1c876..463fcad 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1196,6 +1196,83 @@ static void nf_tables_chain_destroy(struct nft_chain *chain)
 	}
 }
 
+struct nft_chain_hook {
+	u32				num;
+	u32				priority;
+	const struct nf_chain_type	*type;
+	struct net_device		*dev;
+};
+
+static int nft_chain_parse_hook(struct net *net,
+				const struct nlattr * const nla[],
+				struct nft_af_info *afi,
+				struct nft_chain_hook *hook, bool create)
+{
+	struct nlattr *ha[NFTA_HOOK_MAX + 1];
+	const struct nf_chain_type *type;
+	struct net_device *dev;
+	int err;
+
+	err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK],
+			       nft_hook_policy);
+	if (err < 0)
+		return err;
+
+	if (ha[NFTA_HOOK_HOOKNUM] == NULL ||
+	    ha[NFTA_HOOK_PRIORITY] == NULL)
+		return -EINVAL;
+
+	hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
+	if (hook->num >= afi->nhooks)
+		return -EINVAL;
+
+	hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
+
+	type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT];
+	if (nla[NFTA_CHAIN_TYPE]) {
+		type = nf_tables_chain_type_lookup(afi, nla[NFTA_CHAIN_TYPE],
+						   create);
+		if (IS_ERR(type))
+			return PTR_ERR(type);
+	}
+	if (!(type->hook_mask & (1 << hook->num)))
+		return -EOPNOTSUPP;
+	if (!try_module_get(type->owner))
+		return -ENOENT;
+
+	hook->type = type;
+
+	hook->dev = NULL;
+	if (afi->flags & NFT_AF_NEEDS_DEV) {
+		char ifname[IFNAMSIZ];
+
+		if (!ha[NFTA_HOOK_DEV]) {
+			module_put(type->owner);
+			return -EOPNOTSUPP;
+		}
+
+		nla_strlcpy(ifname, ha[NFTA_HOOK_DEV], IFNAMSIZ);
+		dev = dev_get_by_name(net, ifname);
+		if (!dev) {
+			module_put(type->owner);
+			return -ENOENT;
+		}
+		hook->dev = dev;
+	} else if (ha[NFTA_HOOK_DEV]) {
+		module_put(type->owner);
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static void nft_chain_release_hook(struct nft_chain_hook *hook)
+{
+	module_put(hook->type->owner);
+	if (hook->dev != NULL)
+		dev_put(hook->dev);
+}
+
 static int nf_tables_newchain(struct net *net, struct sock *nlsk,
 			      struct sk_buff *skb, const struct nlmsghdr *nlh,
 			      const struct nlattr * const nla[])
@@ -1206,10 +1283,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
 	struct nft_table *table;
 	struct nft_chain *chain;
 	struct nft_base_chain *basechain = NULL;
-	struct nlattr *ha[NFTA_HOOK_MAX + 1];
 	u8 genmask = nft_genmask_next(net);
 	int family = nfmsg->nfgen_family;
-	struct net_device *dev = NULL;
 	u8 policy = NF_ACCEPT;
 	u64 handle = 0;
 	unsigned int i;
@@ -1320,102 +1395,53 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
 		return -EOVERFLOW;
 
 	if (nla[NFTA_CHAIN_HOOK]) {
-		const struct nf_chain_type *type;
+		struct nft_chain_hook hook;
 		struct nf_hook_ops *ops;
 		nf_hookfn *hookfn;
-		u32 hooknum, priority;
-
-		type = chain_type[family][NFT_CHAIN_T_DEFAULT];
-		if (nla[NFTA_CHAIN_TYPE]) {
-			type = nf_tables_chain_type_lookup(afi,
-							   nla[NFTA_CHAIN_TYPE],
-							   create);
-			if (IS_ERR(type))
-				return PTR_ERR(type);
-		}
 
-		err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK],
-				       nft_hook_policy);
+		err = nft_chain_parse_hook(net, nla, afi, &hook, create);
 		if (err < 0)
 			return err;
-		if (ha[NFTA_HOOK_HOOKNUM] == NULL ||
-		    ha[NFTA_HOOK_PRIORITY] == NULL)
-			return -EINVAL;
-
-		hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
-		if (hooknum >= afi->nhooks)
-			return -EINVAL;
-		priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
-
-		if (!(type->hook_mask & (1 << hooknum)))
-			return -EOPNOTSUPP;
-		if (!try_module_get(type->owner))
-			return -ENOENT;
-		hookfn = type->hooks[hooknum];
-
-		if (afi->flags & NFT_AF_NEEDS_DEV) {
-			char ifname[IFNAMSIZ];
-
-			if (!ha[NFTA_HOOK_DEV]) {
-				module_put(type->owner);
-				return -EOPNOTSUPP;
-			}
-
-			nla_strlcpy(ifname, ha[NFTA_HOOK_DEV], IFNAMSIZ);
-			dev = dev_get_by_name(net, ifname);
-			if (!dev) {
-				module_put(type->owner);
-				return -ENOENT;
-			}
-		} else if (ha[NFTA_HOOK_DEV]) {
-			module_put(type->owner);
-			return -EOPNOTSUPP;
-		}
 
 		basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
 		if (basechain == NULL) {
-			module_put(type->owner);
-			if (dev != NULL)
-				dev_put(dev);
+			nft_chain_release_hook(&hook);
 			return -ENOMEM;
 		}
 
-		if (dev != NULL)
-			strncpy(basechain->dev_name, dev->name, IFNAMSIZ);
+		if (hook.dev != NULL)
+			strncpy(basechain->dev_name, hook.dev->name, IFNAMSIZ);
 
 		if (nla[NFTA_CHAIN_COUNTERS]) {
 			stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
 			if (IS_ERR(stats)) {
-				module_put(type->owner);
+				nft_chain_release_hook(&hook);
 				kfree(basechain);
-				if (dev != NULL)
-					dev_put(dev);
 				return PTR_ERR(stats);
 			}
 			basechain->stats = stats;
 		} else {
 			stats = netdev_alloc_pcpu_stats(struct nft_stats);
 			if (stats == NULL) {
-				module_put(type->owner);
+				nft_chain_release_hook(&hook);
 				kfree(basechain);
-				if (dev != NULL)
-					dev_put(dev);
 				return -ENOMEM;
 			}
 			rcu_assign_pointer(basechain->stats, stats);
 		}
 
-		basechain->type = type;
+		hookfn = hook.type->hooks[hook.num];
+		basechain->type = hook.type;
 		chain = &basechain->chain;
 
 		for (i = 0; i < afi->nops; i++) {
 			ops = &basechain->ops[i];
 			ops->pf		= family;
-			ops->hooknum	= hooknum;
-			ops->priority	= priority;
+			ops->hooknum	= hook.num;
+			ops->priority	= hook.priority;
 			ops->priv	= chain;
 			ops->hook	= afi->hooks[ops->hooknum];
-			ops->dev	= dev;
+			ops->dev	= hook.dev;
 			if (hookfn)
 				ops->hook = hookfn;
 			if (afi->hook_ops_init)
-- 
2.1.4

  parent reply	other threads:[~2016-09-05 10:58 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-05 10:58 [PATCH 00/29] Netfilter updates for net-next Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 01/29] netfilter: conntrack: Only need first 4 bytes to get l4proto ports Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 02/29] netfilter: physdev: add missed blank Pablo Neira Ayuso
2016-09-05 17:43   ` Joe Perches
2016-09-05 10:58 ` [PATCH 03/29] netfilter: nf_dup4: remove redundant checksum recalculation Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 04/29] netfilter: use_nf_conn_expires helper in more places Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 05/29] ipvs: use nf_ct_kill helper Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 06/29] netfilter: nf_tables: rename set implementations Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 07/29] netfilter: nf_tables: add hash expression Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 08/29] netfilter: remove ip_conntrack* sysctl compat code Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 09/29] netfilter: conntrack: simplify the code by using nf_conntrack_get_ht Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 10/29] netfilter: nf_conntrack: restore nf_conntrack_htable_size as exported symbol Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 11/29] netfilter: nf_tables: add quota expression Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 12/29] netfilter: nf_tables: add number generator expression Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 13/29] netfilter: fix spelling mistake: "delimitter" -> "delimiter" Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 14/29] netfilter: nft_hash: fix non static symbol warning Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 15/29] netfilter: nf_tables: typo in trace attribute definition Pablo Neira Ayuso
2016-09-05 10:58 ` Pablo Neira Ayuso [this message]
2016-09-05 10:58 ` [PATCH 17/29] netfilter: nf_tables: reject hook configuration updates on existing chains Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 18/29] rhashtable: add rhashtable_lookup_get_insert_key() Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 19/29] netfilter: nf_tables: honor NLM_F_EXCL flag in set element insertion Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 20/29] netfilter: nf_tables: Use nla_put_be32() to dump immediate parameters Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 21/29] netfilter: restart search if moved to other chain Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 22/29] netfilter: don't rely on DYING bit to detect when destroy event was sent Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 23/29] netfilter: conntrack: get rid of conntrack timer Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 24/29] netfilter: evict stale entries on netlink dumps Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 25/29] netfilter: conntrack: add gc worker to remove timed-out entries Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 26/29] netfilter: conntrack: resched gc again if eviction rate is high Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 27/29] netfilter: remove __nf_ct_kill_acct helper Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 28/29] netfilter: log_arp: Use ARPHRD_ETHER instead of literal '1' Pablo Neira Ayuso
2016-09-05 10:58 ` [PATCH 29/29] netfilter: log: Check param to avoid overflow in nf_log_set Pablo Neira Ayuso
2016-09-06 19:47 ` [PATCH 00/29] Netfilter updates for net-next David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1473073124-5015-17-git-send-email-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).