All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] Netfilter updates for net-next
@ 2016-01-08 14:02 Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 01/17] netfilter: nf_tables: release objects on netns destruction Pablo Neira Ayuso
                   ` (17 more replies)
  0 siblings, 18 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

Hi David,

The following patchset contains Netfilter updates for net-next, they are:

1) Release nf_tables objects on netns destructions via
   nft_release_afinfo().

2) Destroy basechain and rules on netdevice removal in the new netdev
   family.

3) Get rid of defensive check against removal of inactive objects in
   nf_tables.

4) Pass down netns pointer to our existing nfnetlink callbacks, as well
   as commit() and abort() nfnetlink callbacks.

5) Allow to invert limit expression in nf_tables, so we can throttle
   overlimit traffic.

6) Add packet duplication for the netdev family.

7) Add forward expression for the netdev family.

8) Define pr_fmt() in conntrack helpers.

9) Don't leave nfqueue configuration on inconsistent state in case of
   errors, from Ken-ichirou MATSUZAWA, follow up patches are also from
   him.

10) Skip queue option handling after unbind.

11) Return error on unknown both in nfqueue and nflog command.

12) Autoload ctnetlink when NFQA_CFG_F_CONNTRACK is set.

13) Add new NFTA_SET_USERDATA attribute to store user data in sets,
    from Carlos Falgueras.

14) Add support for 64 bit byteordering changes nf_tables, from Florian
    Westphal.

15) Add conntrack byte/packet counter matching support to nf_tables,
    also from Florian.

You can pull these changes from:

  git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git

Thanks!

----------------------------------------------------------------

The following changes since commit 26a4d063b1357e3ad81b776eb89d4d82f101da2c:

  Merge branch 'bnxt_en-next' (2015-12-28 00:57:29 -0500)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git HEAD

for you to fetch changes up to 48f66c905a976bf0ff092fc24f08d9addd82a245:

  netfilter: nft_ct: add byte/packet counter support (2016-01-08 14:44:09 +0100)

----------------------------------------------------------------
Carlos Falgueras García (1):
      netfilter: nf_tables: Add new attributes into nft_set to store user data.

Florian Westphal (2):
      netfilter: nft_byteorder: provide 64bit le/be conversion
      netfilter: nft_ct: add byte/packet counter support

Ken-ichirou MATSUZAWA (5):
      netfilter: nfnetlink_queue: validate dependencies to avoid breaking atomicity
      netfilter: nfnetlink_queue: don't handle options after unbind
      netfilter: nfnetlink_queue: just returns error for unknown command
      netfilter: nfnetlink_queue: autoload nf_conntrack_netlink module NFQA_CFG_F_CONNTRACK config flag
      netfilter: nfnetlink_log: just returns error for unknown command

Pablo Neira Ayuso (9):
      netfilter: nf_tables: release objects on netns destruction
      netfilter: nf_tables: destroy basechain and rules on netdevice removal
      netfilter: nf_tables: remove check against removal of inactive objects
      netfilter: nfnetlink: pass down netns pointer to call() and call_rcu()
      netfilter: nfnetlink: pass down netns pointer to commit() and abort() callbacks
      netfilter: nft_limit: allow to invert matching criteria
      netfilter: nf_tables: add packet duplication to the netdev family
      netfilter: nf_tables: add forward expression to the netdev family
      netfilter: nf_ct_helper: define pr_fmt()

 include/linux/netfilter/nfnetlink.h      |  12 +--
 include/net/netfilter/nf_dup_netdev.h    |   6 ++
 include/net/netfilter/nf_tables.h        |  11 ++-
 include/uapi/linux/netfilter/nf_tables.h |  22 +++++
 net/bridge/netfilter/nf_tables_bridge.c  |   2 +-
 net/ipv4/netfilter/nf_tables_arp.c       |   2 +-
 net/ipv4/netfilter/nf_tables_ipv4.c      |   2 +-
 net/ipv6/netfilter/nf_tables_ipv6.c      |   2 +-
 net/netfilter/Kconfig                    |  22 +++++
 net/netfilter/Makefile                   |   7 ++
 net/netfilter/ipset/ip_set_core.c        | 108 +++++++++-----------
 net/netfilter/nf_conntrack_ftp.c         |  17 ++--
 net/netfilter/nf_conntrack_irc.c         |   7 +-
 net/netfilter/nf_conntrack_netlink.c     |  96 ++++++++----------
 net/netfilter/nf_conntrack_sane.c        |  19 ++--
 net/netfilter/nf_conntrack_sip.c         |   5 +-
 net/netfilter/nf_conntrack_tftp.c        |   7 +-
 net/netfilter/nf_dup_netdev.c            |  40 ++++++++
 net/netfilter/nf_tables_api.c            | 164 +++++++++++++++++++++----------
 net/netfilter/nf_tables_inet.c           |   2 +-
 net/netfilter/nf_tables_netdev.c         |  47 ++++-----
 net/netfilter/nfnetlink.c                |  12 +--
 net/netfilter/nfnetlink_acct.c           |  21 ++--
 net/netfilter/nfnetlink_cthelper.c       |  18 ++--
 net/netfilter/nfnetlink_cttimeout.c      |  42 ++++----
 net/netfilter/nfnetlink_log.c            |  17 ++--
 net/netfilter/nfnetlink_queue.c          | 123 +++++++++++------------
 net/netfilter/nft_byteorder.c            |  23 +++++
 net/netfilter/nft_compat.c               |   6 +-
 net/netfilter/nft_ct.c                   |  38 +++++++
 net/netfilter/nft_dup_netdev.c           |  97 ++++++++++++++++++
 net/netfilter/nft_fwd_netdev.c           |  98 ++++++++++++++++++
 net/netfilter/nft_limit.c                |  16 ++-
 net/netfilter/xt_osf.c                   |   7 +-
 34 files changed, 749 insertions(+), 369 deletions(-)
 create mode 100644 include/net/netfilter/nf_dup_netdev.h
 create mode 100644 net/netfilter/nf_dup_netdev.c
 create mode 100644 net/netfilter/nft_dup_netdev.c
 create mode 100644 net/netfilter/nft_fwd_netdev.c
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 01/17] netfilter: nf_tables: release objects on netns destruction
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 02/17] netfilter: nf_tables: destroy basechain and rules on netdevice removal Pablo Neira Ayuso
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

We have to release the existing objects on netns removal otherwise we
leak them. Chains are unregistered in first place to make sure no
packets are walking on our rules and sets anymore.

The object release happens by when we unregister the family via
nft_release_afinfo() which is called from nft_unregister_afinfo() from
the corresponding __net_exit path in every family.

Reported-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/net/netfilter/nf_tables.h       |  2 +-
 net/bridge/netfilter/nf_tables_bridge.c |  2 +-
 net/ipv4/netfilter/nf_tables_arp.c      |  2 +-
 net/ipv4/netfilter/nf_tables_ipv4.c     |  2 +-
 net/ipv6/netfilter/nf_tables_ipv6.c     |  2 +-
 net/netfilter/nf_tables_api.c           | 47 +++++++++++++++++++++++++++++++--
 net/netfilter/nf_tables_inet.c          |  2 +-
 net/netfilter/nf_tables_netdev.c        |  2 +-
 8 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index b313cda..a50f139 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -880,7 +880,7 @@ struct nft_af_info {
 };
 
 int nft_register_afinfo(struct net *, struct nft_af_info *);
-void nft_unregister_afinfo(struct nft_af_info *);
+void nft_unregister_afinfo(struct net *, struct nft_af_info *);
 
 int nft_register_chain_type(const struct nf_chain_type *);
 void nft_unregister_chain_type(const struct nf_chain_type *);
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index 62f6b1b..7fcdd72 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -141,7 +141,7 @@ err:
 
 static void nf_tables_bridge_exit_net(struct net *net)
 {
-	nft_unregister_afinfo(net->nft.bridge);
+	nft_unregister_afinfo(net, net->nft.bridge);
 	kfree(net->nft.bridge);
 }
 
diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c
index 9d09d4f..cd84d42 100644
--- a/net/ipv4/netfilter/nf_tables_arp.c
+++ b/net/ipv4/netfilter/nf_tables_arp.c
@@ -57,7 +57,7 @@ err:
 
 static void nf_tables_arp_exit_net(struct net *net)
 {
-	nft_unregister_afinfo(net->nft.arp);
+	nft_unregister_afinfo(net, net->nft.arp);
 	kfree(net->nft.arp);
 }
 
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c
index ca9dc3c..e44ba3b 100644
--- a/net/ipv4/netfilter/nf_tables_ipv4.c
+++ b/net/ipv4/netfilter/nf_tables_ipv4.c
@@ -78,7 +78,7 @@ err:
 
 static void nf_tables_ipv4_exit_net(struct net *net)
 {
-	nft_unregister_afinfo(net->nft.ipv4);
+	nft_unregister_afinfo(net, net->nft.ipv4);
 	kfree(net->nft.ipv4);
 }
 
diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c
index 120ea91..30b22f4 100644
--- a/net/ipv6/netfilter/nf_tables_ipv6.c
+++ b/net/ipv6/netfilter/nf_tables_ipv6.c
@@ -77,7 +77,7 @@ err:
 
 static void nf_tables_ipv6_exit_net(struct net *net)
 {
-	nft_unregister_afinfo(net->nft.ipv6);
+	nft_unregister_afinfo(net, net->nft.ipv6);
 	kfree(net->nft.ipv6);
 }
 
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 4a23f77..8522731 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -41,6 +41,8 @@ int nft_register_afinfo(struct net *net, struct nft_af_info *afi)
 }
 EXPORT_SYMBOL_GPL(nft_register_afinfo);
 
+static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi);
+
 /**
  *	nft_unregister_afinfo - unregister nf_tables address family info
  *
@@ -48,9 +50,10 @@ EXPORT_SYMBOL_GPL(nft_register_afinfo);
  *
  *	Unregister the address family for use with nf_tables.
  */
-void nft_unregister_afinfo(struct nft_af_info *afi)
+void nft_unregister_afinfo(struct net *net, struct nft_af_info *afi)
 {
 	nfnl_lock(NFNL_SUBSYS_NFTABLES);
+	__nft_release_afinfo(net, afi);
 	list_del_rcu(&afi->list);
 	nfnl_unlock(NFNL_SUBSYS_NFTABLES);
 }
@@ -4579,7 +4582,7 @@ int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
 }
 EXPORT_SYMBOL_GPL(nft_data_dump);
 
-static int nf_tables_init_net(struct net *net)
+static int __net_init nf_tables_init_net(struct net *net)
 {
 	INIT_LIST_HEAD(&net->nft.af_info);
 	INIT_LIST_HEAD(&net->nft.commit_list);
@@ -4587,6 +4590,46 @@ static int nf_tables_init_net(struct net *net)
 	return 0;
 }
 
+/* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */
+static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
+{
+	struct nft_table *table, *nt;
+	struct nft_chain *chain, *nc;
+	struct nft_rule *rule, *nr;
+	struct nft_set *set, *ns;
+	struct nft_ctx ctx = {
+		.net	= net,
+		.afi	= afi,
+	};
+
+	list_for_each_entry_safe(table, nt, &afi->tables, list) {
+		list_for_each_entry(chain, &table->chains, list)
+			nf_tables_unregister_hooks(table, chain, afi->nops);
+		/* No packets are walking on these chains anymore. */
+		ctx.table = table;
+		list_for_each_entry(chain, &table->chains, list) {
+			ctx.chain = chain;
+			list_for_each_entry_safe(rule, nr, &chain->rules, list) {
+				list_del(&rule->list);
+				chain->use--;
+				nf_tables_rule_destroy(&ctx, rule);
+			}
+		}
+		list_for_each_entry_safe(set, ns, &table->sets, list) {
+			list_del(&set->list);
+			table->use--;
+			nft_set_destroy(set);
+		}
+		list_for_each_entry_safe(chain, nc, &table->chains, list) {
+			list_del(&chain->list);
+			table->use--;
+			nf_tables_chain_destroy(chain);
+		}
+		list_del(&table->list);
+		nf_tables_table_destroy(&ctx);
+	}
+}
+
 static struct pernet_operations nf_tables_net_ops = {
 	.init	= nf_tables_init_net,
 };
diff --git a/net/netfilter/nf_tables_inet.c b/net/netfilter/nf_tables_inet.c
index 9dd2d21..6b5f762 100644
--- a/net/netfilter/nf_tables_inet.c
+++ b/net/netfilter/nf_tables_inet.c
@@ -57,7 +57,7 @@ err:
 
 static void __net_exit nf_tables_inet_exit_net(struct net *net)
 {
-	nft_unregister_afinfo(net->nft.inet);
+	nft_unregister_afinfo(net, net->nft.inet);
 	kfree(net->nft.inet);
 }
 
diff --git a/net/netfilter/nf_tables_netdev.c b/net/netfilter/nf_tables_netdev.c
index 7b9c053..2bfd1fb 100644
--- a/net/netfilter/nf_tables_netdev.c
+++ b/net/netfilter/nf_tables_netdev.c
@@ -139,7 +139,7 @@ err:
 
 static void nf_tables_netdev_exit_net(struct net *net)
 {
-	nft_unregister_afinfo(net->nft.netdev);
+	nft_unregister_afinfo(net, net->nft.netdev);
 	kfree(net->nft.netdev);
 }
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 02/17] netfilter: nf_tables: destroy basechain and rules on netdevice removal
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 01/17] netfilter: nf_tables: release objects on netns destruction Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 03/17] netfilter: nf_tables: remove check against removal of inactive objects Pablo Neira Ayuso
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

If the netdevice is destroyed, the resources that are attached should
be released too as they belong to the device that is now gone.

Suggested-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/net/netfilter/nf_tables.h |  5 +----
 net/netfilter/nf_tables_api.c     | 31 +++++++++++++++++++++------
 net/netfilter/nf_tables_netdev.c  | 45 ++++++++++++++++-----------------------
 3 files changed, 44 insertions(+), 37 deletions(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index a50f139..0191fbb 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -821,10 +821,7 @@ static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chai
 	return container_of(chain, struct nft_base_chain, chain);
 }
 
-int nft_register_basechain(struct nft_base_chain *basechain,
-			   unsigned int hook_nops);
-void nft_unregister_basechain(struct nft_base_chain *basechain,
-			      unsigned int hook_nops);
+int __nft_release_basechain(struct nft_ctx *ctx);
 
 unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv);
 
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 8522731..5729844 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -131,8 +131,8 @@ static void nft_trans_destroy(struct nft_trans *trans)
 	kfree(trans);
 }
 
-int nft_register_basechain(struct nft_base_chain *basechain,
-			   unsigned int hook_nops)
+static int nft_register_basechain(struct nft_base_chain *basechain,
+				  unsigned int hook_nops)
 {
 	struct net *net = read_pnet(&basechain->pnet);
 
@@ -141,10 +141,9 @@ int nft_register_basechain(struct nft_base_chain *basechain,
 
 	return nf_register_net_hooks(net, basechain->ops, hook_nops);
 }
-EXPORT_SYMBOL_GPL(nft_register_basechain);
 
-void nft_unregister_basechain(struct nft_base_chain *basechain,
-			      unsigned int hook_nops)
+static void nft_unregister_basechain(struct nft_base_chain *basechain,
+				     unsigned int hook_nops)
 {
 	struct net *net = read_pnet(&basechain->pnet);
 
@@ -153,7 +152,6 @@ void nft_unregister_basechain(struct nft_base_chain *basechain,
 
 	nf_unregister_net_hooks(net, basechain->ops, hook_nops);
 }
-EXPORT_SYMBOL_GPL(nft_unregister_basechain);
 
 static int nf_tables_register_hooks(const struct nft_table *table,
 				    struct nft_chain *chain,
@@ -4590,6 +4588,27 @@ static int __net_init nf_tables_init_net(struct net *net)
 	return 0;
 }
 
+int __nft_release_basechain(struct nft_ctx *ctx)
+{
+	struct nft_rule *rule, *nr;
+
+	BUG_ON(!(ctx->chain->flags & NFT_BASE_CHAIN));
+
+	nf_tables_unregister_hooks(ctx->chain->table, ctx->chain,
+				   ctx->afi->nops);
+	list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
+		list_del(&rule->list);
+		ctx->chain->use--;
+		nf_tables_rule_destroy(ctx, rule);
+	}
+	list_del(&ctx->chain->list);
+	ctx->table->use--;
+	nf_tables_chain_destroy(ctx->chain);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(__nft_release_basechain);
+
 /* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */
 static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
 {
diff --git a/net/netfilter/nf_tables_netdev.c b/net/netfilter/nf_tables_netdev.c
index 2bfd1fb..3e9c87b 100644
--- a/net/netfilter/nf_tables_netdev.c
+++ b/net/netfilter/nf_tables_netdev.c
@@ -156,35 +156,17 @@ static const struct nf_chain_type nft_filter_chain_netdev = {
 	.hook_mask	= (1 << NF_NETDEV_INGRESS),
 };
 
-static void nft_netdev_event(unsigned long event, struct nft_af_info *afi,
-			     struct net_device *dev, struct nft_table *table,
-			     struct nft_base_chain *basechain)
+static void nft_netdev_event(unsigned long event, struct net_device *dev,
+			     struct nft_ctx *ctx)
 {
-	switch (event) {
-	case NETDEV_REGISTER:
-		if (strcmp(basechain->dev_name, dev->name) != 0)
-			return;
+	struct nft_base_chain *basechain = nft_base_chain(ctx->chain);
 
-		BUG_ON(!(basechain->flags & NFT_BASECHAIN_DISABLED));
-
-		dev_hold(dev);
-		basechain->ops[0].dev = dev;
-		basechain->flags &= ~NFT_BASECHAIN_DISABLED;
-		if (!(table->flags & NFT_TABLE_F_DORMANT))
-			nft_register_basechain(basechain, afi->nops);
-		break;
+	switch (event) {
 	case NETDEV_UNREGISTER:
 		if (strcmp(basechain->dev_name, dev->name) != 0)
 			return;
 
-		BUG_ON(basechain->flags & NFT_BASECHAIN_DISABLED);
-
-		if (!(table->flags & NFT_TABLE_F_DORMANT))
-			nft_unregister_basechain(basechain, afi->nops);
-
-		dev_put(basechain->ops[0].dev);
-		basechain->ops[0].dev = NULL;
-		basechain->flags |= NFT_BASECHAIN_DISABLED;
+		__nft_release_basechain(ctx);
 		break;
 	case NETDEV_CHANGENAME:
 		if (dev->ifindex != basechain->ops[0].dev->ifindex)
@@ -201,20 +183,29 @@ static int nf_tables_netdev_event(struct notifier_block *this,
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 	struct nft_af_info *afi;
 	struct nft_table *table;
-	struct nft_chain *chain;
+	struct nft_chain *chain, *nr;
+	struct nft_ctx ctx = {
+		.net	= dev_net(dev),
+	};
+
+	if (event != NETDEV_UNREGISTER &&
+	    event != NETDEV_CHANGENAME)
+		return NOTIFY_DONE;
 
 	nfnl_lock(NFNL_SUBSYS_NFTABLES);
 	list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) {
+		ctx.afi = afi;
 		if (afi->family != NFPROTO_NETDEV)
 			continue;
 
 		list_for_each_entry(table, &afi->tables, list) {
-			list_for_each_entry(chain, &table->chains, list) {
+			ctx.table = table;
+			list_for_each_entry_safe(chain, nr, &table->chains, list) {
 				if (!(chain->flags & NFT_BASE_CHAIN))
 					continue;
 
-				nft_netdev_event(event, afi, dev, table,
-						 nft_base_chain(chain));
+				ctx.chain = chain;
+				nft_netdev_event(event, dev, &ctx);
 			}
 		}
 	}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 03/17] netfilter: nf_tables: remove check against removal of inactive objects
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 01/17] netfilter: nf_tables: release objects on netns destruction Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 02/17] netfilter: nf_tables: destroy basechain and rules on netdevice removal Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 04/17] netfilter: nfnetlink: pass down netns pointer to call() and call_rcu() Pablo Neira Ayuso
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

The following sequence inside a batch, although not very useful, is
valid:

 add table foo
 ...
 delete table foo

This may be generated by some robot while applying some incremental
upgrade, so remove the defensive checks against this.

This patch keeps the check on the get/dump path by now, we have to
replace the inactive flag by introducing object generations.

Reported-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nf_tables_api.c | 29 +++++++++--------------------
 1 file changed, 9 insertions(+), 20 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 5729844..28cbc45 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -832,8 +832,6 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk,
 	table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]);
 	if (IS_ERR(table))
 		return PTR_ERR(table);
-	if (table->flags & NFT_TABLE_INACTIVE)
-		return -ENOENT;
 
 	ctx.afi = afi;
 	ctx.table = table;
@@ -1493,14 +1491,10 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
 	table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
 	if (IS_ERR(table))
 		return PTR_ERR(table);
-	if (table->flags & NFT_TABLE_INACTIVE)
-		return -ENOENT;
 
 	chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]);
 	if (IS_ERR(chain))
 		return PTR_ERR(chain);
-	if (chain->flags & NFT_CHAIN_INACTIVE)
-		return -ENOENT;
 	if (chain->use > 0)
 		return -EBUSY;
 
@@ -2192,8 +2186,6 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
 	table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
 	if (IS_ERR(table))
 		return PTR_ERR(table);
-	if (table->flags & NFT_TABLE_INACTIVE)
-		return -ENOENT;
 
 	if (nla[NFTA_RULE_CHAIN]) {
 		chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
@@ -2362,8 +2354,6 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
 		table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
 		if (IS_ERR(table))
 			return PTR_ERR(table);
-		if (table->flags & NFT_TABLE_INACTIVE)
-			return -ENOENT;
 	}
 
 	nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla);
@@ -2898,8 +2888,6 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk,
 	set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
 	if (IS_ERR(set))
 		return PTR_ERR(set);
-	if (set->flags & NFT_SET_INACTIVE)
-		return -ENOENT;
 	if (!list_empty(&set->bindings))
 		return -EBUSY;
 
@@ -3022,8 +3010,7 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX +
 static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
 				      const struct sk_buff *skb,
 				      const struct nlmsghdr *nlh,
-				      const struct nlattr * const nla[],
-				      bool trans)
+				      const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	struct nft_af_info *afi;
@@ -3036,8 +3023,6 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
 	table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE]);
 	if (IS_ERR(table))
 		return PTR_ERR(table);
-	if (!trans && (table->flags & NFT_TABLE_INACTIVE))
-		return -ENOENT;
 
 	nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla);
 	return 0;
@@ -3146,9 +3131,11 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
 		return err;
 
 	err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh,
-					 (void *)nla, false);
+					 (void *)nla);
 	if (err < 0)
 		return err;
+	if (ctx.table->flags & NFT_TABLE_INACTIVE)
+		return -ENOENT;
 
 	set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
 	if (IS_ERR(set))
@@ -3212,9 +3199,11 @@ static int nf_tables_getsetelem(struct sock *nlsk, struct sk_buff *skb,
 	struct nft_ctx ctx;
 	int err;
 
-	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, false);
+	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
 	if (err < 0)
 		return err;
+	if (ctx.table->flags & NFT_TABLE_INACTIVE)
+		return -ENOENT;
 
 	set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
 	if (IS_ERR(set))
@@ -3536,7 +3525,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
 	if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
 		return -EINVAL;
 
-	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, true);
+	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
 	if (err < 0)
 		return err;
 
@@ -3630,7 +3619,7 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
 	if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
 		return -EINVAL;
 
-	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, false);
+	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
 	if (err < 0)
 		return err;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 04/17] netfilter: nfnetlink: pass down netns pointer to call() and call_rcu()
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (2 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 03/17] netfilter: nf_tables: remove check against removal of inactive objects Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 05/17] netfilter: nfnetlink: pass down netns pointer to commit() and abort() callbacks Pablo Neira Ayuso
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

Adapt callsites to avoid recurrent lookup of the netns pointer.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter/nfnetlink.h  |   8 +--
 net/netfilter/ipset/ip_set_core.c    | 108 +++++++++++++++--------------------
 net/netfilter/nf_conntrack_netlink.c |  96 ++++++++++++++-----------------
 net/netfilter/nf_tables_api.c        |  30 ++++------
 net/netfilter/nfnetlink.c            |   6 +-
 net/netfilter/nfnetlink_acct.c       |  21 +++----
 net/netfilter/nfnetlink_cthelper.c   |  18 +++---
 net/netfilter/nfnetlink_cttimeout.c  |  42 ++++++--------
 net/netfilter/nfnetlink_log.c        |  15 ++---
 net/netfilter/nfnetlink_queue.c      |  36 +++++-------
 net/netfilter/nft_compat.c           |   6 +-
 net/netfilter/xt_osf.c               |   7 ++-
 12 files changed, 173 insertions(+), 220 deletions(-)

diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 5646b24..ceacbf5 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -8,12 +8,12 @@
 #include <uapi/linux/netfilter/nfnetlink.h>
 
 struct nfnl_callback {
-	int (*call)(struct sock *nl, struct sk_buff *skb, 
-		    const struct nlmsghdr *nlh,
-		    const struct nlattr * const cda[]);
-	int (*call_rcu)(struct sock *nl, struct sk_buff *skb, 
+	int (*call)(struct net *net, struct sock *nl, struct sk_buff *skb,
 		    const struct nlmsghdr *nlh,
 		    const struct nlattr * const cda[]);
+	int (*call_rcu)(struct net *net, struct sock *nl, struct sk_buff *skb,
+			const struct nlmsghdr *nlh,
+			const struct nlattr * const cda[]);
 	int (*call_batch)(struct net *net, struct sock *nl, struct sk_buff *skb,
 			  const struct nlmsghdr *nlh,
 			  const struct nlattr * const cda[]);
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 54f3d7c..95db43f 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -825,20 +825,17 @@ find_free_id(struct ip_set_net *inst, const char *name, ip_set_id_t *index,
 	return 0;
 }
 
-static int
-ip_set_none(struct sock *ctnl, struct sk_buff *skb,
-	    const struct nlmsghdr *nlh,
-	    const struct nlattr * const attr[])
+static int ip_set_none(struct net *net, struct sock *ctnl, struct sk_buff *skb,
+		       const struct nlmsghdr *nlh,
+		       const struct nlattr * const attr[])
 {
 	return -EOPNOTSUPP;
 }
 
-static int
-ip_set_create(struct sock *ctnl, struct sk_buff *skb,
-	      const struct nlmsghdr *nlh,
-	      const struct nlattr * const attr[])
+static int ip_set_create(struct net *net, struct sock *ctnl,
+			 struct sk_buff *skb, const struct nlmsghdr *nlh,
+			 const struct nlattr * const attr[])
 {
-	struct net *net = sock_net(ctnl);
 	struct ip_set_net *inst = ip_set_pernet(net);
 	struct ip_set *set, *clash = NULL;
 	ip_set_id_t index = IPSET_INVALID_ID;
@@ -976,12 +973,11 @@ ip_set_destroy_set(struct ip_set *set)
 	kfree(set);
 }
 
-static int
-ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
-	       const struct nlmsghdr *nlh,
-	       const struct nlattr * const attr[])
+static int ip_set_destroy(struct net *net, struct sock *ctnl,
+			  struct sk_buff *skb, const struct nlmsghdr *nlh,
+			  const struct nlattr * const attr[])
 {
-	struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
+	struct ip_set_net *inst = ip_set_pernet(net);
 	struct ip_set *s;
 	ip_set_id_t i;
 	int ret = 0;
@@ -1052,12 +1048,11 @@ ip_set_flush_set(struct ip_set *set)
 	spin_unlock_bh(&set->lock);
 }
 
-static int
-ip_set_flush(struct sock *ctnl, struct sk_buff *skb,
-	     const struct nlmsghdr *nlh,
-	     const struct nlattr * const attr[])
+static int ip_set_flush(struct net *net, struct sock *ctnl, struct sk_buff *skb,
+			const struct nlmsghdr *nlh,
+			const struct nlattr * const attr[])
 {
-	struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
+	struct ip_set_net *inst = ip_set_pernet(net);
 	struct ip_set *s;
 	ip_set_id_t i;
 
@@ -1092,12 +1087,11 @@ ip_set_setname2_policy[IPSET_ATTR_CMD_MAX + 1] = {
 				    .len = IPSET_MAXNAMELEN - 1 },
 };
 
-static int
-ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
-	      const struct nlmsghdr *nlh,
-	      const struct nlattr * const attr[])
+static int ip_set_rename(struct net *net, struct sock *ctnl,
+			 struct sk_buff *skb, const struct nlmsghdr *nlh,
+			 const struct nlattr * const attr[])
 {
-	struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
+	struct ip_set_net *inst = ip_set_pernet(net);
 	struct ip_set *set, *s;
 	const char *name2;
 	ip_set_id_t i;
@@ -1142,12 +1136,11 @@ out:
  * so the ip_set_list always contains valid pointers to the sets.
  */
 
-static int
-ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
-	    const struct nlmsghdr *nlh,
-	    const struct nlattr * const attr[])
+static int ip_set_swap(struct net *net, struct sock *ctnl, struct sk_buff *skb,
+		       const struct nlmsghdr *nlh,
+		       const struct nlattr * const attr[])
 {
-	struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
+	struct ip_set_net *inst = ip_set_pernet(net);
 	struct ip_set *from, *to;
 	ip_set_id_t from_id, to_id;
 	char from_name[IPSET_MAXNAMELEN];
@@ -1413,10 +1406,9 @@ out:
 	return ret < 0 ? ret : skb->len;
 }
 
-static int
-ip_set_dump(struct sock *ctnl, struct sk_buff *skb,
-	    const struct nlmsghdr *nlh,
-	    const struct nlattr * const attr[])
+static int ip_set_dump(struct net *net, struct sock *ctnl, struct sk_buff *skb,
+		       const struct nlmsghdr *nlh,
+		       const struct nlattr * const attr[])
 {
 	if (unlikely(protocol_failed(attr)))
 		return -IPSET_ERR_PROTOCOL;
@@ -1500,12 +1492,11 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
 	return ret;
 }
 
-static int
-ip_set_uadd(struct sock *ctnl, struct sk_buff *skb,
-	    const struct nlmsghdr *nlh,
-	    const struct nlattr * const attr[])
+static int ip_set_uadd(struct net *net, struct sock *ctnl, struct sk_buff *skb,
+		       const struct nlmsghdr *nlh,
+		       const struct nlattr * const attr[])
 {
-	struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
+	struct ip_set_net *inst = ip_set_pernet(net);
 	struct ip_set *set;
 	struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
 	const struct nlattr *nla;
@@ -1555,12 +1546,11 @@ ip_set_uadd(struct sock *ctnl, struct sk_buff *skb,
 	return ret;
 }
 
-static int
-ip_set_udel(struct sock *ctnl, struct sk_buff *skb,
-	    const struct nlmsghdr *nlh,
-	    const struct nlattr * const attr[])
+static int ip_set_udel(struct net *net, struct sock *ctnl, struct sk_buff *skb,
+		       const struct nlmsghdr *nlh,
+		       const struct nlattr * const attr[])
 {
-	struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
+	struct ip_set_net *inst = ip_set_pernet(net);
 	struct ip_set *set;
 	struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
 	const struct nlattr *nla;
@@ -1610,12 +1600,11 @@ ip_set_udel(struct sock *ctnl, struct sk_buff *skb,
 	return ret;
 }
 
-static int
-ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
-	     const struct nlmsghdr *nlh,
-	     const struct nlattr * const attr[])
+static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
+			const struct nlmsghdr *nlh,
+			const struct nlattr * const attr[])
 {
-	struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
+	struct ip_set_net *inst = ip_set_pernet(net);
 	struct ip_set *set;
 	struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
 	int ret = 0;
@@ -1646,12 +1635,11 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
 
 /* Get headed data of a set */
 
-static int
-ip_set_header(struct sock *ctnl, struct sk_buff *skb,
-	      const struct nlmsghdr *nlh,
-	      const struct nlattr * const attr[])
+static int ip_set_header(struct net *net, struct sock *ctnl,
+			 struct sk_buff *skb, const struct nlmsghdr *nlh,
+			 const struct nlattr * const attr[])
 {
-	struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
+	struct ip_set_net *inst = ip_set_pernet(net);
 	const struct ip_set *set;
 	struct sk_buff *skb2;
 	struct nlmsghdr *nlh2;
@@ -1703,10 +1691,9 @@ static const struct nla_policy ip_set_type_policy[IPSET_ATTR_CMD_MAX + 1] = {
 	[IPSET_ATTR_FAMILY]	= { .type = NLA_U8 },
 };
 
-static int
-ip_set_type(struct sock *ctnl, struct sk_buff *skb,
-	    const struct nlmsghdr *nlh,
-	    const struct nlattr * const attr[])
+static int ip_set_type(struct net *net, struct sock *ctnl, struct sk_buff *skb,
+		       const struct nlmsghdr *nlh,
+		       const struct nlattr * const attr[])
 {
 	struct sk_buff *skb2;
 	struct nlmsghdr *nlh2;
@@ -1762,10 +1749,9 @@ ip_set_protocol_policy[IPSET_ATTR_CMD_MAX + 1] = {
 	[IPSET_ATTR_PROTOCOL]	= { .type = NLA_U8 },
 };
 
-static int
-ip_set_protocol(struct sock *ctnl, struct sk_buff *skb,
-		const struct nlmsghdr *nlh,
-		const struct nlattr * const attr[])
+static int ip_set_protocol(struct net *net, struct sock *ctnl,
+			   struct sk_buff *skb, const struct nlmsghdr *nlh,
+			   const struct nlattr * const attr[])
 {
 	struct sk_buff *skb2;
 	struct nlmsghdr *nlh2;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9f52729..dbb1bb3 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1113,12 +1113,11 @@ static int ctnetlink_flush_conntrack(struct net *net,
 	return 0;
 }
 
-static int
-ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
-			const struct nlmsghdr *nlh,
-			const struct nlattr * const cda[])
+static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
+				   struct sk_buff *skb,
+				   const struct nlmsghdr *nlh,
+				   const struct nlattr * const cda[])
 {
-	struct net *net = sock_net(ctnl);
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conntrack_tuple tuple;
 	struct nf_conn *ct;
@@ -1168,12 +1167,11 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
 	return 0;
 }
 
-static int
-ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
-			const struct nlmsghdr *nlh,
-			const struct nlattr * const cda[])
+static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl,
+				   struct sk_buff *skb,
+				   const struct nlmsghdr *nlh,
+				   const struct nlattr * const cda[])
 {
-	struct net *net = sock_net(ctnl);
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conntrack_tuple tuple;
 	struct nf_conn *ct;
@@ -1330,10 +1328,10 @@ ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb)
 	return ctnetlink_dump_list(skb, cb, true);
 }
 
-static int
-ctnetlink_get_ct_dying(struct sock *ctnl, struct sk_buff *skb,
-		       const struct nlmsghdr *nlh,
-		       const struct nlattr * const cda[])
+static int ctnetlink_get_ct_dying(struct net *net, struct sock *ctnl,
+				  struct sk_buff *skb,
+				  const struct nlmsghdr *nlh,
+				  const struct nlattr * const cda[])
 {
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct netlink_dump_control c = {
@@ -1352,10 +1350,10 @@ ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb)
 	return ctnetlink_dump_list(skb, cb, false);
 }
 
-static int
-ctnetlink_get_ct_unconfirmed(struct sock *ctnl, struct sk_buff *skb,
-			     const struct nlmsghdr *nlh,
-			     const struct nlattr * const cda[])
+static int ctnetlink_get_ct_unconfirmed(struct net *net, struct sock *ctnl,
+					struct sk_buff *skb,
+					const struct nlmsghdr *nlh,
+					const struct nlattr * const cda[])
 {
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct netlink_dump_control c = {
@@ -1865,12 +1863,11 @@ err1:
 	return ERR_PTR(err);
 }
 
-static int
-ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
-			const struct nlmsghdr *nlh,
-			const struct nlattr * const cda[])
+static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,
+				   struct sk_buff *skb,
+				   const struct nlmsghdr *nlh,
+				   const struct nlattr * const cda[])
 {
-	struct net *net = sock_net(ctnl);
 	struct nf_conntrack_tuple otuple, rtuple;
 	struct nf_conntrack_tuple_hash *h = NULL;
 	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -2034,10 +2031,10 @@ ctnetlink_ct_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
-static int
-ctnetlink_stat_ct_cpu(struct sock *ctnl, struct sk_buff *skb,
-		      const struct nlmsghdr *nlh,
-		      const struct nlattr * const cda[])
+static int ctnetlink_stat_ct_cpu(struct net *net, struct sock *ctnl,
+				 struct sk_buff *skb,
+				 const struct nlmsghdr *nlh,
+				 const struct nlattr * const cda[])
 {
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct netlink_dump_control c = {
@@ -2080,10 +2077,9 @@ nlmsg_failure:
 	return -1;
 }
 
-static int
-ctnetlink_stat_ct(struct sock *ctnl, struct sk_buff *skb,
-		  const struct nlmsghdr *nlh,
-		  const struct nlattr * const cda[])
+static int ctnetlink_stat_ct(struct net *net, struct sock *ctnl,
+			     struct sk_buff *skb, const struct nlmsghdr *nlh,
+			     const struct nlattr * const cda[])
 {
 	struct sk_buff *skb2;
 	int err;
@@ -2729,12 +2725,12 @@ out:
 	return skb->len;
 }
 
-static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb,
+static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
+				 struct sk_buff *skb,
 				 const struct nlmsghdr *nlh,
 				 const struct nlattr * const cda[])
 {
 	int err;
-	struct net *net = sock_net(ctnl);
 	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	u_int8_t u3 = nfmsg->nfgen_family;
 	struct nf_conntrack_tuple tuple;
@@ -2768,12 +2764,10 @@ static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb,
 	return err;
 }
 
-static int
-ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
-		     const struct nlmsghdr *nlh,
-		     const struct nlattr * const cda[])
+static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
+				struct sk_buff *skb, const struct nlmsghdr *nlh,
+				const struct nlattr * const cda[])
 {
-	struct net *net = sock_net(ctnl);
 	struct nf_conntrack_tuple tuple;
 	struct nf_conntrack_expect *exp;
 	struct sk_buff *skb2;
@@ -2784,7 +2778,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
 
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		if (cda[CTA_EXPECT_MASTER])
-			return ctnetlink_dump_exp_ct(ctnl, skb, nlh, cda);
+			return ctnetlink_dump_exp_ct(net, ctnl, skb, nlh, cda);
 		else {
 			struct netlink_dump_control c = {
 				.dump = ctnetlink_exp_dump_table,
@@ -2850,12 +2844,10 @@ out:
 	return err == -EAGAIN ? -ENOBUFS : err;
 }
 
-static int
-ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
-		     const struct nlmsghdr *nlh,
-		     const struct nlattr * const cda[])
+static int ctnetlink_del_expect(struct net *net, struct sock *ctnl,
+				struct sk_buff *skb, const struct nlmsghdr *nlh,
+				const struct nlattr * const cda[])
 {
-	struct net *net = sock_net(ctnl);
 	struct nf_conntrack_expect *exp;
 	struct nf_conntrack_tuple tuple;
 	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -3136,12 +3128,10 @@ err_ct:
 	return err;
 }
 
-static int
-ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
-		     const struct nlmsghdr *nlh,
-		     const struct nlattr * const cda[])
+static int ctnetlink_new_expect(struct net *net, struct sock *ctnl,
+				struct sk_buff *skb, const struct nlmsghdr *nlh,
+				const struct nlattr * const cda[])
 {
-	struct net *net = sock_net(ctnl);
 	struct nf_conntrack_tuple tuple;
 	struct nf_conntrack_expect *exp;
 	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -3242,10 +3232,10 @@ ctnetlink_exp_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
-static int
-ctnetlink_stat_exp_cpu(struct sock *ctnl, struct sk_buff *skb,
-		       const struct nlmsghdr *nlh,
-		       const struct nlattr * const cda[])
+static int ctnetlink_stat_exp_cpu(struct net *net, struct sock *ctnl,
+				  struct sk_buff *skb,
+				  const struct nlmsghdr *nlh,
+				  const struct nlattr * const cda[])
 {
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct netlink_dump_control c = {
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 28cbc45..69cb5be 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -543,15 +543,14 @@ done:
 	return skb->len;
 }
 
-static int nf_tables_gettable(struct sock *nlsk, struct sk_buff *skb,
-			      const struct nlmsghdr *nlh,
+static int nf_tables_gettable(struct net *net, 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 nft_af_info *afi;
 	const struct nft_table *table;
 	struct sk_buff *skb2;
-	struct net *net = sock_net(skb->sk);
 	int family = nfmsg->nfgen_family;
 	int err;
 
@@ -1097,8 +1096,8 @@ done:
 	return skb->len;
 }
 
-static int nf_tables_getchain(struct sock *nlsk, struct sk_buff *skb,
-			      const struct nlmsghdr *nlh,
+static int nf_tables_getchain(struct net *net, struct sock *nlsk,
+			      struct sk_buff *skb, const struct nlmsghdr *nlh,
 			      const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -1106,7 +1105,6 @@ static int nf_tables_getchain(struct sock *nlsk, struct sk_buff *skb,
 	const struct nft_table *table;
 	const struct nft_chain *chain;
 	struct sk_buff *skb2;
-	struct net *net = sock_net(skb->sk);
 	int family = nfmsg->nfgen_family;
 	int err;
 
@@ -1923,8 +1921,8 @@ done:
 	return skb->len;
 }
 
-static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb,
-			     const struct nlmsghdr *nlh,
+static int nf_tables_getrule(struct net *net, struct sock *nlsk,
+			     struct sk_buff *skb, const struct nlmsghdr *nlh,
 			     const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -1933,7 +1931,6 @@ static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb,
 	const struct nft_chain *chain;
 	const struct nft_rule *rule;
 	struct sk_buff *skb2;
-	struct net *net = sock_net(skb->sk);
 	int family = nfmsg->nfgen_family;
 	int err;
 
@@ -2604,11 +2601,10 @@ static int nf_tables_dump_sets_done(struct netlink_callback *cb)
 	return 0;
 }
 
-static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
-			    const struct nlmsghdr *nlh,
+static int nf_tables_getset(struct net *net, struct sock *nlsk,
+			    struct sk_buff *skb, const struct nlmsghdr *nlh,
 			    const struct nlattr * const nla[])
 {
-	struct net *net = sock_net(skb->sk);
 	const struct nft_set *set;
 	struct nft_ctx ctx;
 	struct sk_buff *skb2;
@@ -3190,11 +3186,10 @@ nla_put_failure:
 	return -ENOSPC;
 }
 
-static int nf_tables_getsetelem(struct sock *nlsk, struct sk_buff *skb,
-				const struct nlmsghdr *nlh,
+static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
+				struct sk_buff *skb, const struct nlmsghdr *nlh,
 				const struct nlattr * const nla[])
 {
-	struct net *net = sock_net(skb->sk);
 	const struct nft_set *set;
 	struct nft_ctx ctx;
 	int err;
@@ -3723,11 +3718,10 @@ err:
 	return err;
 }
 
-static int nf_tables_getgen(struct sock *nlsk, struct sk_buff *skb,
-			    const struct nlmsghdr *nlh,
+static int nf_tables_getgen(struct net *net, struct sock *nlsk,
+			    struct sk_buff *skb, const struct nlmsghdr *nlh,
 			    const struct nlattr * const nla[])
 {
-	struct net *net = sock_net(skb->sk);
 	struct sk_buff *skb2;
 	int err;
 
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 9ed4534..7012154 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -206,7 +206,7 @@ replay:
 		}
 
 		if (nc->call_rcu) {
-			err = nc->call_rcu(net->nfnl, skb, nlh,
+			err = nc->call_rcu(net, net->nfnl, skb, nlh,
 					   (const struct nlattr **)cda);
 			rcu_read_unlock();
 		} else {
@@ -216,8 +216,8 @@ replay:
 			    nfnetlink_find_client(type, ss) != nc)
 				err = -EAGAIN;
 			else if (nc->call)
-				err = nc->call(net->nfnl, skb, nlh,
-						   (const struct nlattr **)cda);
+				err = nc->call(net, net->nfnl, skb, nlh,
+					       (const struct nlattr **)cda);
 			else
 				err = -EINVAL;
 			nfnl_unlock(subsys_id);
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index fefbf5f..5274b04 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -46,12 +46,11 @@ struct nfacct_filter {
 #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES)
 #define NFACCT_OVERQUOTA_BIT	2	/* NFACCT_F_OVERQUOTA */
 
-static int
-nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,
-	     const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+static int nfnl_acct_new(struct net *net, struct sock *nfnl,
+			 struct sk_buff *skb, const struct nlmsghdr *nlh,
+			 const struct nlattr * const tb[])
 {
 	struct nf_acct *nfacct, *matching = NULL;
-	struct net *net = sock_net(nfnl);
 	char *acct_name;
 	unsigned int size = 0;
 	u32 flags = 0;
@@ -253,11 +252,10 @@ nfacct_filter_alloc(const struct nlattr * const attr)
 	return filter;
 }
 
-static int
-nfnl_acct_get(struct sock *nfnl, struct sk_buff *skb,
-	     const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+static int nfnl_acct_get(struct net *net, struct sock *nfnl,
+			 struct sk_buff *skb, const struct nlmsghdr *nlh,
+			 const struct nlattr * const tb[])
 {
-	struct net *net = sock_net(nfnl);
 	int ret = -ENOENT;
 	struct nf_acct *cur;
 	char *acct_name;
@@ -333,11 +331,10 @@ static int nfnl_acct_try_del(struct nf_acct *cur)
 	return ret;
 }
 
-static int
-nfnl_acct_del(struct sock *nfnl, struct sk_buff *skb,
-	     const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+static int nfnl_acct_del(struct net *net, struct sock *nfnl,
+			 struct sk_buff *skb, const struct nlmsghdr *nlh,
+			 const struct nlattr * const tb[])
 {
-	struct net *net = sock_net(nfnl);
 	char *acct_name;
 	struct nf_acct *cur;
 	int ret = -ENOENT;
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c
index 54330fb..e924e95 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -286,9 +286,9 @@ nfnl_cthelper_update(const struct nlattr * const tb[],
 	return 0;
 }
 
-static int
-nfnl_cthelper_new(struct sock *nfnl, struct sk_buff *skb,
-		  const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+static int nfnl_cthelper_new(struct net *net, struct sock *nfnl,
+			     struct sk_buff *skb, const struct nlmsghdr *nlh,
+			     const struct nlattr * const tb[])
 {
 	const char *helper_name;
 	struct nf_conntrack_helper *cur, *helper = NULL;
@@ -498,9 +498,9 @@ out:
 	return skb->len;
 }
 
-static int
-nfnl_cthelper_get(struct sock *nfnl, struct sk_buff *skb,
-		  const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+static int nfnl_cthelper_get(struct net *net, struct sock *nfnl,
+			     struct sk_buff *skb, const struct nlmsghdr *nlh,
+			     const struct nlattr * const tb[])
 {
 	int ret = -ENOENT, i;
 	struct nf_conntrack_helper *cur;
@@ -570,9 +570,9 @@ nfnl_cthelper_get(struct sock *nfnl, struct sk_buff *skb,
 	return ret;
 }
 
-static int
-nfnl_cthelper_del(struct sock *nfnl, struct sk_buff *skb,
-	     const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
+			     struct sk_buff *skb, const struct nlmsghdr *nlh,
+			     const struct nlattr * const tb[])
 {
 	char *helper_name = NULL;
 	struct nf_conntrack_helper *cur;
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index 3921d54..5d010f2 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -65,16 +65,15 @@ ctnl_timeout_parse_policy(void *timeouts, struct nf_conntrack_l4proto *l4proto,
 	return ret;
 }
 
-static int
-cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
-		      const struct nlmsghdr *nlh,
-		      const struct nlattr * const cda[])
+static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
+				 struct sk_buff *skb,
+				 const struct nlmsghdr *nlh,
+				 const struct nlattr * const cda[])
 {
 	__u16 l3num;
 	__u8 l4num;
 	struct nf_conntrack_l4proto *l4proto;
 	struct ctnl_timeout *timeout, *matching = NULL;
-	struct net *net = sock_net(skb->sk);
 	char *name;
 	int ret;
 
@@ -239,12 +238,11 @@ ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
-static int
-cttimeout_get_timeout(struct sock *ctnl, struct sk_buff *skb,
-		      const struct nlmsghdr *nlh,
-		      const struct nlattr * const cda[])
+static int cttimeout_get_timeout(struct net *net, struct sock *ctnl,
+				 struct sk_buff *skb,
+				 const struct nlmsghdr *nlh,
+				 const struct nlattr * const cda[])
 {
-	struct net *net = sock_net(skb->sk);
 	int ret = -ENOENT;
 	char *name;
 	struct ctnl_timeout *cur;
@@ -339,15 +337,14 @@ static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
 	return ret;
 }
 
-static int
-cttimeout_del_timeout(struct sock *ctnl, struct sk_buff *skb,
-		      const struct nlmsghdr *nlh,
-		      const struct nlattr * const cda[])
+static int cttimeout_del_timeout(struct net *net, struct sock *ctnl,
+				 struct sk_buff *skb,
+				 const struct nlmsghdr *nlh,
+				 const struct nlattr * const cda[])
 {
-	struct net *net = sock_net(skb->sk);
-	char *name;
 	struct ctnl_timeout *cur;
 	int ret = -ENOENT;
+	char *name;
 
 	if (!cda[CTA_TIMEOUT_NAME]) {
 		list_for_each_entry(cur, &net->nfct_timeout_list, head)
@@ -370,15 +367,14 @@ cttimeout_del_timeout(struct sock *ctnl, struct sk_buff *skb,
 	return ret;
 }
 
-static int
-cttimeout_default_set(struct sock *ctnl, struct sk_buff *skb,
-		      const struct nlmsghdr *nlh,
-		      const struct nlattr * const cda[])
+static int cttimeout_default_set(struct net *net, struct sock *ctnl,
+				 struct sk_buff *skb,
+				 const struct nlmsghdr *nlh,
+				 const struct nlattr * const cda[])
 {
 	__u16 l3num;
 	__u8 l4num;
 	struct nf_conntrack_l4proto *l4proto;
-	struct net *net = sock_net(skb->sk);
 	unsigned int *timeouts;
 	int ret;
 
@@ -460,14 +456,14 @@ nla_put_failure:
 	return -1;
 }
 
-static int cttimeout_default_get(struct sock *ctnl, struct sk_buff *skb,
+static int cttimeout_default_get(struct net *net, struct sock *ctnl,
+				 struct sk_buff *skb,
 				 const struct nlmsghdr *nlh,
 				 const struct nlattr * const cda[])
 {
 	__u16 l3num;
 	__u8 l4num;
 	struct nf_conntrack_l4proto *l4proto;
-	struct net *net = sock_net(skb->sk);
 	struct sk_buff *skb2;
 	int ret, err;
 
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 70b6bd3..6a57f10 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -785,10 +785,9 @@ static struct notifier_block nfulnl_rtnl_notifier = {
 	.notifier_call	= nfulnl_rcv_nl_event,
 };
 
-static int
-nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
-		   const struct nlmsghdr *nlh,
-		   const struct nlattr * const nfqa[])
+static int nfulnl_recv_unsupp(struct net *net, struct sock *ctnl,
+			      struct sk_buff *skb, const struct nlmsghdr *nlh,
+			      const struct nlattr * const nfqa[])
 {
 	return -ENOTSUPP;
 }
@@ -809,16 +808,14 @@ static const struct nla_policy nfula_cfg_policy[NFULA_CFG_MAX+1] = {
 	[NFULA_CFG_FLAGS]	= { .type = NLA_U16 },
 };
 
-static int
-nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
-		   const struct nlmsghdr *nlh,
-		   const struct nlattr * const nfula[])
+static int nfulnl_recv_config(struct net *net, struct sock *ctnl,
+			      struct sk_buff *skb, const struct nlmsghdr *nlh,
+			      const struct nlattr * const nfula[])
 {
 	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	u_int16_t group_num = ntohs(nfmsg->res_id);
 	struct nfulnl_instance *inst;
 	struct nfulnl_msg_config_cmd *cmd = NULL;
-	struct net *net = sock_net(ctnl);
 	struct nfnl_log_net *log = nfnl_log_pernet(net);
 	int ret = 0;
 	u16 flags = 0;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 861c661..3d1f16c 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -957,10 +957,10 @@ static int nfq_id_after(unsigned int id, unsigned int max)
 	return (int)(id - max) > 0;
 }
 
-static int
-nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb,
-		   const struct nlmsghdr *nlh,
-		   const struct nlattr * const nfqa[])
+static int nfqnl_recv_verdict_batch(struct net *net, struct sock *ctnl,
+				    struct sk_buff *skb,
+				    const struct nlmsghdr *nlh,
+			            const struct nlattr * const nfqa[])
 {
 	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	struct nf_queue_entry *entry, *tmp;
@@ -969,8 +969,6 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb,
 	struct nfqnl_instance *queue;
 	LIST_HEAD(batch_list);
 	u16 queue_num = ntohs(nfmsg->res_id);
-
-	struct net *net = sock_net(ctnl);
 	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
 
 	queue = verdict_instance_lookup(q, queue_num,
@@ -1029,14 +1027,13 @@ static struct nf_conn *nfqnl_ct_parse(struct nfnl_ct_hook *nfnl_ct,
 	return ct;
 }
 
-static int
-nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
-		   const struct nlmsghdr *nlh,
-		   const struct nlattr * const nfqa[])
+static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl,
+			      struct sk_buff *skb,
+			      const struct nlmsghdr *nlh,
+			      const struct nlattr * const nfqa[])
 {
 	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	u_int16_t queue_num = ntohs(nfmsg->res_id);
-
 	struct nfqnl_msg_verdict_hdr *vhdr;
 	struct nfqnl_instance *queue;
 	unsigned int verdict;
@@ -1044,8 +1041,6 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
 	enum ip_conntrack_info uninitialized_var(ctinfo);
 	struct nfnl_ct_hook *nfnl_ct;
 	struct nf_conn *ct = NULL;
-
-	struct net *net = sock_net(ctnl);
 	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
 
 	queue = instance_lookup(q, queue_num);
@@ -1092,10 +1087,9 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
 	return 0;
 }
 
-static int
-nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
-		  const struct nlmsghdr *nlh,
-		  const struct nlattr * const nfqa[])
+static int nfqnl_recv_unsupp(struct net *net, struct sock *ctnl,
+			     struct sk_buff *skb, const struct nlmsghdr *nlh,
+			     const struct nlattr * const nfqa[])
 {
 	return -ENOTSUPP;
 }
@@ -1110,16 +1104,14 @@ static const struct nf_queue_handler nfqh = {
 	.nf_hook_drop	= &nfqnl_nf_hook_drop,
 };
 
-static int
-nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
-		  const struct nlmsghdr *nlh,
-		  const struct nlattr * const nfqa[])
+static int nfqnl_recv_config(struct net *net, struct sock *ctnl,
+			     struct sk_buff *skb, const struct nlmsghdr *nlh,
+			     const struct nlattr * const nfqa[])
 {
 	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	u_int16_t queue_num = ntohs(nfmsg->res_id);
 	struct nfqnl_instance *queue;
 	struct nfqnl_msg_config_cmd *cmd = NULL;
-	struct net *net = sock_net(ctnl);
 	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
 	int ret = 0;
 
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 9c8fab0..454841b 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -519,9 +519,9 @@ nla_put_failure:
 	return -1;
 }
 
-static int
-nfnl_compat_get(struct sock *nfnl, struct sk_buff *skb,
-		const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+static int nfnl_compat_get(struct net *net, struct sock *nfnl,
+			   struct sk_buff *skb, const struct nlmsghdr *nlh,
+			   const struct nlattr * const tb[])
 {
 	int ret = 0, target;
 	struct nfgenmsg *nfmsg;
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index df8801e..4e3c3af 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -61,8 +61,8 @@ static const struct nla_policy xt_osf_policy[OSF_ATTR_MAX + 1] = {
 	[OSF_ATTR_FINGER]	= { .len = sizeof(struct xt_osf_user_finger) },
 };
 
-static int xt_osf_add_callback(struct sock *ctnl, struct sk_buff *skb,
-			       const struct nlmsghdr *nlh,
+static int xt_osf_add_callback(struct net *net, struct sock *ctnl,
+			       struct sk_buff *skb, const struct nlmsghdr *nlh,
 			       const struct nlattr * const osf_attrs[])
 {
 	struct xt_osf_user_finger *f;
@@ -104,7 +104,8 @@ static int xt_osf_add_callback(struct sock *ctnl, struct sk_buff *skb,
 	return err;
 }
 
-static int xt_osf_remove_callback(struct sock *ctnl, struct sk_buff *skb,
+static int xt_osf_remove_callback(struct net *net, struct sock *ctnl,
+				  struct sk_buff *skb,
 				  const struct nlmsghdr *nlh,
 				  const struct nlattr * const osf_attrs[])
 {
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 05/17] netfilter: nfnetlink: pass down netns pointer to commit() and abort() callbacks
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (3 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 04/17] netfilter: nfnetlink: pass down netns pointer to call() and call_rcu() Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 06/17] netfilter: nft_limit: allow to invert matching criteria Pablo Neira Ayuso
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

Adapt callsites to avoid recurrent lookup of the netns pointer.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter/nfnetlink.h | 4 ++--
 net/netfilter/nf_tables_api.c       | 6 ++----
 net/netfilter/nfnetlink.c           | 6 +++---
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index ceacbf5..ba0d978 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -26,8 +26,8 @@ struct nfnetlink_subsystem {
 	__u8 subsys_id;			/* nfnetlink subsystem ID */
 	__u8 cb_count;			/* number of callbacks */
 	const struct nfnl_callback *cb;	/* callback for individual types */
-	int (*commit)(struct sk_buff *skb);
-	int (*abort)(struct sk_buff *skb);
+	int (*commit)(struct net *net, struct sk_buff *skb);
+	int (*abort)(struct net *net, struct sk_buff *skb);
 };
 
 int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n);
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 69cb5be..f5c3971 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3865,9 +3865,8 @@ static void nf_tables_commit_release(struct nft_trans *trans)
 	kfree(trans);
 }
 
-static int nf_tables_commit(struct sk_buff *skb)
+static int nf_tables_commit(struct net *net, struct sk_buff *skb)
 {
-	struct net *net = sock_net(skb->sk);
 	struct nft_trans *trans, *next;
 	struct nft_trans_elem *te;
 
@@ -4002,9 +4001,8 @@ static void nf_tables_abort_release(struct nft_trans *trans)
 	kfree(trans);
 }
 
-static int nf_tables_abort(struct sk_buff *skb)
+static int nf_tables_abort(struct net *net, struct sk_buff *skb)
 {
-	struct net *net = sock_net(skb->sk);
 	struct nft_trans *trans, *next;
 	struct nft_trans_elem *te;
 
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 7012154..a7ba233 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -425,15 +425,15 @@ next:
 	}
 done:
 	if (status & NFNL_BATCH_REPLAY) {
-		ss->abort(oskb);
+		ss->abort(net, oskb);
 		nfnl_err_reset(&err_list);
 		nfnl_unlock(subsys_id);
 		kfree_skb(skb);
 		goto replay;
 	} else if (status == NFNL_BATCH_DONE) {
-		ss->commit(oskb);
+		ss->commit(net, oskb);
 	} else {
-		ss->abort(oskb);
+		ss->abort(net, oskb);
 	}
 
 	nfnl_err_deliver(&err_list, oskb);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 06/17] netfilter: nft_limit: allow to invert matching criteria
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (4 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 05/17] netfilter: nfnetlink: pass down netns pointer to commit() and abort() callbacks Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 07/17] netfilter: nf_tables: add packet duplication to the netdev family Pablo Neira Ayuso
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

This patch allows you to invert the ratelimit matching criteria, so you
can match packets over the ratelimit. This is required to support what
hashlimit does.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/uapi/linux/netfilter/nf_tables.h |  6 ++++++
 net/netfilter/nft_limit.c                | 16 +++++++++++++---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index b48a3ab..22043ce 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -780,6 +780,10 @@ enum nft_limit_type {
 	NFT_LIMIT_PKT_BYTES
 };
 
+enum nft_limit_flags {
+	NFT_LIMIT_F_INV	= (1 << 0),
+};
+
 /**
  * enum nft_limit_attributes - nf_tables limit expression netlink attributes
  *
@@ -787,6 +791,7 @@ enum nft_limit_type {
  * @NFTA_LIMIT_UNIT: refill unit (NLA_U64)
  * @NFTA_LIMIT_BURST: burst (NLA_U32)
  * @NFTA_LIMIT_TYPE: type of limit (NLA_U32: enum nft_limit_type)
+ * @NFTA_LIMIT_FLAGS: flags (NLA_U32: enum nft_limit_flags)
  */
 enum nft_limit_attributes {
 	NFTA_LIMIT_UNSPEC,
@@ -794,6 +799,7 @@ enum nft_limit_attributes {
 	NFTA_LIMIT_UNIT,
 	NFTA_LIMIT_BURST,
 	NFTA_LIMIT_TYPE,
+	NFTA_LIMIT_FLAGS,
 	__NFTA_LIMIT_MAX
 };
 #define NFTA_LIMIT_MAX		(__NFTA_LIMIT_MAX - 1)
diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c
index 5d67938..99d1857 100644
--- a/net/netfilter/nft_limit.c
+++ b/net/netfilter/nft_limit.c
@@ -26,6 +26,7 @@ struct nft_limit {
 	u64		rate;
 	u64		nsecs;
 	u32		burst;
+	bool		invert;
 };
 
 static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
@@ -44,11 +45,11 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
 	if (delta >= 0) {
 		limit->tokens = delta;
 		spin_unlock_bh(&limit_lock);
-		return false;
+		return limit->invert;
 	}
 	limit->tokens = tokens;
 	spin_unlock_bh(&limit_lock);
-	return true;
+	return !limit->invert;
 }
 
 static int nft_limit_init(struct nft_limit *limit,
@@ -78,6 +79,12 @@ static int nft_limit_init(struct nft_limit *limit,
 
 		limit->rate = rate;
 	}
+	if (tb[NFTA_LIMIT_FLAGS]) {
+		u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS]));
+
+		if (flags & NFT_LIMIT_F_INV)
+			limit->invert = true;
+	}
 	limit->last = ktime_get_ns();
 
 	return 0;
@@ -86,13 +93,15 @@ static int nft_limit_init(struct nft_limit *limit,
 static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit,
 			  enum nft_limit_type type)
 {
+	u32 flags = limit->invert ? NFT_LIMIT_F_INV : 0;
 	u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC);
 	u64 rate = limit->rate - limit->burst;
 
 	if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate)) ||
 	    nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs)) ||
 	    nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(limit->burst)) ||
-	    nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type)))
+	    nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type)) ||
+	    nla_put_be32(skb, NFTA_LIMIT_FLAGS, htonl(flags)))
 		goto nla_put_failure;
 	return 0;
 
@@ -120,6 +129,7 @@ static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = {
 	[NFTA_LIMIT_UNIT]	= { .type = NLA_U64 },
 	[NFTA_LIMIT_BURST]	= { .type = NLA_U32 },
 	[NFTA_LIMIT_TYPE]	= { .type = NLA_U32 },
+	[NFTA_LIMIT_FLAGS]	= { .type = NLA_U32 },
 };
 
 static int nft_limit_pkts_init(const struct nft_ctx *ctx,
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 07/17] netfilter: nf_tables: add packet duplication to the netdev family
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (5 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 06/17] netfilter: nft_limit: allow to invert matching criteria Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 08/17] netfilter: nf_tables: add forward expression " Pablo Neira Ayuso
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

You can use this to duplicate packets and inject them at the egress path
of the specified interface. This duplication allows you to inspect
traffic from the dummy or any other interface dedicated to this purpose.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/net/netfilter/nf_dup_netdev.h |  6 +++
 net/netfilter/Kconfig                 | 16 ++++++
 net/netfilter/Makefile                |  6 +++
 net/netfilter/nf_dup_netdev.c         | 40 +++++++++++++++
 net/netfilter/nft_dup_netdev.c        | 97 +++++++++++++++++++++++++++++++++++
 5 files changed, 165 insertions(+)
 create mode 100644 include/net/netfilter/nf_dup_netdev.h
 create mode 100644 net/netfilter/nf_dup_netdev.c
 create mode 100644 net/netfilter/nft_dup_netdev.c

diff --git a/include/net/netfilter/nf_dup_netdev.h b/include/net/netfilter/nf_dup_netdev.h
new file mode 100644
index 0000000..397dcae
--- /dev/null
+++ b/include/net/netfilter/nf_dup_netdev.h
@@ -0,0 +1,6 @@
+#ifndef _NF_DUP_NETDEV_H_
+#define _NF_DUP_NETDEV_H_
+
+void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif);
+
+#endif
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 4692782..8514cc4 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -563,6 +563,22 @@ config NFT_COMPAT
 	  x_tables match/target extensions over the nf_tables
 	  framework.
 
+if NF_TABLES_NETDEV
+
+config NF_DUP_NETDEV
+	tristate "Netfilter packet duplication support"
+	help
+	  This option enables the generic packet duplication infrastructure
+	  for Netfilter.
+
+config NFT_DUP_NETDEV
+	tristate "Netfilter nf_tables netdev packet duplication support"
+	select NF_DUP_NETDEV
+	help
+	  This option enables packet duplication for the "netdev" family.
+
+endif # NF_TABLES_NETDEV
+
 endif # NF_TABLES
 
 config NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 2293484..5c99133 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -66,6 +66,9 @@ obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
 # SYNPROXY
 obj-$(CONFIG_NETFILTER_SYNPROXY) += nf_synproxy_core.o
 
+# generic packet duplication from netdev family
+obj-$(CONFIG_NF_DUP_NETDEV)	+= nf_dup_netdev.o
+
 # nf_tables
 nf_tables-objs += nf_tables_core.o nf_tables_api.o nf_tables_trace.o
 nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o nft_dynset.o
@@ -90,6 +93,9 @@ obj-$(CONFIG_NFT_LOG)		+= nft_log.o
 obj-$(CONFIG_NFT_MASQ)		+= nft_masq.o
 obj-$(CONFIG_NFT_REDIR)		+= nft_redir.o
 
+# nf_tables netdev
+obj-$(CONFIG_NFT_DUP_NETDEV)	+= nft_dup_netdev.o
+
 # generic X tables 
 obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
 
diff --git a/net/netfilter/nf_dup_netdev.c b/net/netfilter/nf_dup_netdev.c
new file mode 100644
index 0000000..8414ee1
--- /dev/null
+++ b/net/netfilter/nf_dup_netdev.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+
+void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif)
+{
+	struct net_device *dev;
+	struct sk_buff *skb;
+
+	dev = dev_get_by_index_rcu(pkt->net, oif);
+	if (dev == NULL)
+		return;
+
+	skb = skb_clone(pkt->skb, GFP_ATOMIC);
+	if (skb == NULL)
+		return;
+
+	if (skb_mac_header_was_set(skb))
+		skb_push(skb, skb->mac_len);
+
+	skb->dev = dev;
+	skb_sender_cpu_clear(skb);
+	dev_queue_xmit(skb);
+}
+EXPORT_SYMBOL_GPL(nf_dup_netdev_egress);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
diff --git a/net/netfilter/nft_dup_netdev.c b/net/netfilter/nft_dup_netdev.c
new file mode 100644
index 0000000..2cc1e0e
--- /dev/null
+++ b/net/netfilter/nft_dup_netdev.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015 Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_dup_netdev.h>
+
+struct nft_dup_netdev {
+	enum nft_registers	sreg_dev:8;
+};
+
+static void nft_dup_netdev_eval(const struct nft_expr *expr,
+				struct nft_regs *regs,
+				const struct nft_pktinfo *pkt)
+{
+	struct nft_dup_netdev *priv = nft_expr_priv(expr);
+	int oif = regs->data[priv->sreg_dev];
+
+	nf_dup_netdev_egress(pkt, oif);
+}
+
+static const struct nla_policy nft_dup_netdev_policy[NFTA_DUP_MAX + 1] = {
+	[NFTA_DUP_SREG_DEV]	= { .type = NLA_U32 },
+};
+
+static int nft_dup_netdev_init(const struct nft_ctx *ctx,
+			       const struct nft_expr *expr,
+			       const struct nlattr * const tb[])
+{
+	struct nft_dup_netdev *priv = nft_expr_priv(expr);
+
+	if (tb[NFTA_DUP_SREG_DEV] == NULL)
+		return -EINVAL;
+
+	priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
+	return nft_validate_register_load(priv->sreg_dev, sizeof(int));
+}
+
+static const struct nft_expr_ops nft_dup_netdev_ingress_ops;
+
+static int nft_dup_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+	struct nft_dup_netdev *priv = nft_expr_priv(expr);
+
+	if (nft_dump_register(skb, NFTA_DUP_SREG_DEV, priv->sreg_dev))
+		goto nla_put_failure;
+
+	return 0;
+
+nla_put_failure:
+	return -1;
+}
+
+static struct nft_expr_type nft_dup_netdev_type;
+static const struct nft_expr_ops nft_dup_netdev_ops = {
+	.type		= &nft_dup_netdev_type,
+	.size		= NFT_EXPR_SIZE(sizeof(struct nft_dup_netdev)),
+	.eval		= nft_dup_netdev_eval,
+	.init		= nft_dup_netdev_init,
+	.dump		= nft_dup_netdev_dump,
+};
+
+static struct nft_expr_type nft_dup_netdev_type __read_mostly = {
+	.family		= NFPROTO_NETDEV,
+	.name		= "dup",
+	.ops		= &nft_dup_netdev_ops,
+	.policy		= nft_dup_netdev_policy,
+	.maxattr	= NFTA_DUP_MAX,
+	.owner		= THIS_MODULE,
+};
+
+static int __init nft_dup_netdev_module_init(void)
+{
+	return nft_register_expr(&nft_dup_netdev_type);
+}
+
+static void __exit nft_dup_netdev_module_exit(void)
+{
+	nft_unregister_expr(&nft_dup_netdev_type);
+}
+
+module_init(nft_dup_netdev_module_init);
+module_exit(nft_dup_netdev_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
+MODULE_ALIAS_NFT_AF_EXPR(5, "dup");
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 08/17] netfilter: nf_tables: add forward expression to the netdev family
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (6 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 07/17] netfilter: nf_tables: add packet duplication to the netdev family Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 09/17] netfilter: nf_ct_helper: define pr_fmt() Pablo Neira Ayuso
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

You can use this to forward packets from ingress to the egress path of
the specified interface. This provides a fast path to bounce packets
from one interface to another specific destination interface.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/uapi/linux/netfilter/nf_tables.h | 12 ++++
 net/netfilter/Kconfig                    |  6 ++
 net/netfilter/Makefile                   |  1 +
 net/netfilter/nft_fwd_netdev.c           | 98 ++++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+)
 create mode 100644 net/netfilter/nft_fwd_netdev.c

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 22043ce..731288a 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -984,6 +984,18 @@ enum nft_dup_attributes {
 #define NFTA_DUP_MAX		(__NFTA_DUP_MAX - 1)
 
 /**
+ * enum nft_fwd_attributes - nf_tables fwd expression netlink attributes
+ *
+ * @NFTA_FWD_SREG_DEV: source register of output interface (NLA_U32: nft_register)
+ */
+enum nft_fwd_attributes {
+	NFTA_FWD_UNSPEC,
+	NFTA_FWD_SREG_DEV,
+	__NFTA_FWD_MAX
+};
+#define NFTA_FWD_MAX	(__NFTA_FWD_MAX - 1)
+
+/**
  * enum nft_gen_attributes - nf_tables ruleset generation attributes
  *
  * @NFTA_GEN_ID: Ruleset generation ID (NLA_U32)
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 8514cc4..8c067e6 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -577,6 +577,12 @@ config NFT_DUP_NETDEV
 	help
 	  This option enables packet duplication for the "netdev" family.
 
+config NFT_FWD_NETDEV
+	tristate "Netfilter nf_tables netdev packet forwarding support"
+	select NF_DUP_NETDEV
+	help
+	  This option enables packet forwarding for the "netdev" family.
+
 endif # NF_TABLES_NETDEV
 
 endif # NF_TABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 5c99133..6913454 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_NFT_REDIR)		+= nft_redir.o
 
 # nf_tables netdev
 obj-$(CONFIG_NFT_DUP_NETDEV)	+= nft_dup_netdev.o
+obj-$(CONFIG_NFT_FWD_NETDEV)	+= nft_fwd_netdev.o
 
 # generic X tables 
 obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c
new file mode 100644
index 0000000..763ebc3
--- /dev/null
+++ b/net/netfilter/nft_fwd_netdev.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015 Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_dup_netdev.h>
+
+struct nft_fwd_netdev {
+	enum nft_registers	sreg_dev:8;
+};
+
+static void nft_fwd_netdev_eval(const struct nft_expr *expr,
+				struct nft_regs *regs,
+				const struct nft_pktinfo *pkt)
+{
+	struct nft_fwd_netdev *priv = nft_expr_priv(expr);
+	int oif = regs->data[priv->sreg_dev];
+
+	nf_dup_netdev_egress(pkt, oif);
+	regs->verdict.code = NF_DROP;
+}
+
+static const struct nla_policy nft_fwd_netdev_policy[NFTA_FWD_MAX + 1] = {
+	[NFTA_FWD_SREG_DEV]	= { .type = NLA_U32 },
+};
+
+static int nft_fwd_netdev_init(const struct nft_ctx *ctx,
+			       const struct nft_expr *expr,
+			       const struct nlattr * const tb[])
+{
+	struct nft_fwd_netdev *priv = nft_expr_priv(expr);
+
+	if (tb[NFTA_FWD_SREG_DEV] == NULL)
+		return -EINVAL;
+
+	priv->sreg_dev = nft_parse_register(tb[NFTA_FWD_SREG_DEV]);
+	return nft_validate_register_load(priv->sreg_dev, sizeof(int));
+}
+
+static const struct nft_expr_ops nft_fwd_netdev_ingress_ops;
+
+static int nft_fwd_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+	struct nft_fwd_netdev *priv = nft_expr_priv(expr);
+
+	if (nft_dump_register(skb, NFTA_FWD_SREG_DEV, priv->sreg_dev))
+		goto nla_put_failure;
+
+	return 0;
+
+nla_put_failure:
+	return -1;
+}
+
+static struct nft_expr_type nft_fwd_netdev_type;
+static const struct nft_expr_ops nft_fwd_netdev_ops = {
+	.type		= &nft_fwd_netdev_type,
+	.size		= NFT_EXPR_SIZE(sizeof(struct nft_fwd_netdev)),
+	.eval		= nft_fwd_netdev_eval,
+	.init		= nft_fwd_netdev_init,
+	.dump		= nft_fwd_netdev_dump,
+};
+
+static struct nft_expr_type nft_fwd_netdev_type __read_mostly = {
+	.family		= NFPROTO_NETDEV,
+	.name		= "fwd",
+	.ops		= &nft_fwd_netdev_ops,
+	.policy		= nft_fwd_netdev_policy,
+	.maxattr	= NFTA_FWD_MAX,
+	.owner		= THIS_MODULE,
+};
+
+static int __init nft_fwd_netdev_module_init(void)
+{
+	return nft_register_expr(&nft_fwd_netdev_type);
+}
+
+static void __exit nft_fwd_netdev_module_exit(void)
+{
+	nft_unregister_expr(&nft_fwd_netdev_type);
+}
+
+module_init(nft_fwd_netdev_module_init);
+module_exit(nft_fwd_netdev_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
+MODULE_ALIAS_NFT_AF_EXPR(5, "fwd");
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 09/17] netfilter: nf_ct_helper: define pr_fmt()
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (7 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 08/17] netfilter: nf_tables: add forward expression " Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 10/17] netfilter: nfnetlink_queue: validate dependencies to avoid breaking atomicity Pablo Neira Ayuso
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nf_conntrack_ftp.c  | 17 ++++++++---------
 net/netfilter/nf_conntrack_irc.c  |  7 ++++---
 net/netfilter/nf_conntrack_sane.c | 19 +++++++++----------
 net/netfilter/nf_conntrack_sip.c  |  5 +++--
 net/netfilter/nf_conntrack_tftp.c |  7 ++++---
 5 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index b666959..883c691 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/netfilter.h>
@@ -505,11 +507,11 @@ skip_nl_seq:
 		   different IP address.  Simply don't record it for
 		   NAT. */
 		if (cmd.l3num == PF_INET) {
-			pr_debug("conntrack_ftp: NOT RECORDING: %pI4 != %pI4\n",
+			pr_debug("NOT RECORDING: %pI4 != %pI4\n",
 				 &cmd.u3.ip,
 				 &ct->tuplehash[dir].tuple.src.u3.ip);
 		} else {
-			pr_debug("conntrack_ftp: NOT RECORDING: %pI6 != %pI6\n",
+			pr_debug("NOT RECORDING: %pI6 != %pI6\n",
 				 cmd.u3.ip6,
 				 ct->tuplehash[dir].tuple.src.u3.ip6);
 		}
@@ -586,8 +588,7 @@ static void nf_conntrack_ftp_fini(void)
 			if (ftp[i][j].me == NULL)
 				continue;
 
-			pr_debug("nf_ct_ftp: unregistering helper for pf: %d "
-				 "port: %d\n",
+			pr_debug("unregistering helper for pf: %d port: %d\n",
 				 ftp[i][j].tuple.src.l3num, ports[i]);
 			nf_conntrack_helper_unregister(&ftp[i][j]);
 		}
@@ -625,14 +626,12 @@ static int __init nf_conntrack_ftp_init(void)
 			else
 				sprintf(ftp[i][j].name, "ftp-%d", ports[i]);
 
-			pr_debug("nf_ct_ftp: registering helper for pf: %d "
-				 "port: %d\n",
+			pr_debug("registering helper for pf: %d port: %d\n",
 				 ftp[i][j].tuple.src.l3num, ports[i]);
 			ret = nf_conntrack_helper_register(&ftp[i][j]);
 			if (ret) {
-				printk(KERN_ERR "nf_ct_ftp: failed to register"
-				       " helper for pf: %d port: %d\n",
-					ftp[i][j].tuple.src.l3num, ports[i]);
+				pr_err("failed to register helper for pf: %d port: %d\n",
+				       ftp[i][j].tuple.src.l3num, ports[i]);
 				nf_conntrack_ftp_fini();
 				return ret;
 			}
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 0fd2976..8b6da27 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -9,6 +9,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/skbuff.h>
@@ -237,7 +239,7 @@ static int __init nf_conntrack_irc_init(void)
 	int i, ret;
 
 	if (max_dcc_channels < 1) {
-		printk(KERN_ERR "nf_ct_irc: max_dcc_channels must not be zero\n");
+		pr_err("max_dcc_channels must not be zero\n");
 		return -EINVAL;
 	}
 
@@ -267,8 +269,7 @@ static int __init nf_conntrack_irc_init(void)
 
 		ret = nf_conntrack_helper_register(&irc[i]);
 		if (ret) {
-			printk(KERN_ERR "nf_ct_irc: failed to register helper "
-			       "for pf: %u port: %u\n",
+			pr_err("failed to register helper for pf: %u port: %u\n",
 			       irc[i].tuple.src.l3num, ports[i]);
 			nf_conntrack_irc_fini();
 			return ret;
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
index 4a2134f..7523a57 100644
--- a/net/netfilter/nf_conntrack_sane.c
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -17,6 +17,8 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/netfilter.h>
@@ -120,14 +122,14 @@ static int help(struct sk_buff *skb,
 	ct_sane_info->state = SANE_STATE_NORMAL;
 
 	if (datalen < sizeof(struct sane_reply_net_start)) {
-		pr_debug("nf_ct_sane: NET_START reply too short\n");
+		pr_debug("NET_START reply too short\n");
 		goto out;
 	}
 
 	reply = sb_ptr;
 	if (reply->status != htonl(SANE_STATUS_SUCCESS)) {
 		/* saned refused the command */
-		pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
+		pr_debug("unsuccessful SANE_STATUS = %u\n",
 			 ntohl(reply->status));
 		goto out;
 	}
@@ -148,7 +150,7 @@ static int help(struct sk_buff *skb,
 			  &tuple->src.u3, &tuple->dst.u3,
 			  IPPROTO_TCP, NULL, &reply->port);
 
-	pr_debug("nf_ct_sane: expect: ");
+	pr_debug("expect: ");
 	nf_ct_dump_tuple(&exp->tuple);
 
 	/* Can't expect this?  Best to drop packet now. */
@@ -178,8 +180,7 @@ static void nf_conntrack_sane_fini(void)
 
 	for (i = 0; i < ports_c; i++) {
 		for (j = 0; j < 2; j++) {
-			pr_debug("nf_ct_sane: unregistering helper for pf: %d "
-				 "port: %d\n",
+			pr_debug("unregistering helper for pf: %d port: %d\n",
 				 sane[i][j].tuple.src.l3num, ports[i]);
 			nf_conntrack_helper_unregister(&sane[i][j]);
 		}
@@ -216,14 +217,12 @@ static int __init nf_conntrack_sane_init(void)
 			else
 				sprintf(sane[i][j].name, "sane-%d", ports[i]);
 
-			pr_debug("nf_ct_sane: registering helper for pf: %d "
-				 "port: %d\n",
+			pr_debug("registering helper for pf: %d port: %d\n",
 				 sane[i][j].tuple.src.l3num, ports[i]);
 			ret = nf_conntrack_helper_register(&sane[i][j]);
 			if (ret) {
-				printk(KERN_ERR "nf_ct_sane: failed to "
-				       "register helper for pf: %d port: %d\n",
-					sane[i][j].tuple.src.l3num, ports[i]);
+				pr_err("failed to register helper for pf: %d port: %d\n",
+				       sane[i][j].tuple.src.l3num, ports[i]);
 				nf_conntrack_sane_fini();
 				return ret;
 			}
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 885b4ab..3e06402 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/skbuff.h>
@@ -1665,8 +1667,7 @@ static int __init nf_conntrack_sip_init(void)
 
 			ret = nf_conntrack_helper_register(&sip[i][j]);
 			if (ret) {
-				printk(KERN_ERR "nf_ct_sip: failed to register"
-				       " helper for pf: %u port: %u\n",
+				pr_err("failed to register helper for pf: %u port: %u\n",
 				       sip[i][j].tuple.src.l3num, ports[i]);
 				nf_conntrack_sip_fini();
 				return ret;
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index e68ab4f..36f9640 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -5,6 +5,8 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/in.h>
@@ -138,9 +140,8 @@ static int __init nf_conntrack_tftp_init(void)
 
 			ret = nf_conntrack_helper_register(&tftp[i][j]);
 			if (ret) {
-				printk(KERN_ERR "nf_ct_tftp: failed to register"
-				       " helper for pf: %u port: %u\n",
-					tftp[i][j].tuple.src.l3num, ports[i]);
+				pr_err("failed to register helper for pf: %u port: %u\n",
+				       tftp[i][j].tuple.src.l3num, ports[i]);
 				nf_conntrack_tftp_fini();
 				return ret;
 			}
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 10/17] netfilter: nfnetlink_queue: validate dependencies to avoid breaking atomicity
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (8 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 09/17] netfilter: nf_ct_helper: define pr_fmt() Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 11/17] netfilter: nfnetlink_queue: don't handle options after unbind Pablo Neira Ayuso
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

From: Ken-ichirou MATSUZAWA <chamaken@gmail.com>

Check that dependencies are fulfilled before updating the queue
instance, otherwise we can leave things in intermediate state on errors
in nfqnl_recv_config().

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nfnetlink_queue.c | 72 ++++++++++++++++++-----------------------
 1 file changed, 32 insertions(+), 40 deletions(-)

diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 3d1f16c..fe360f7 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1113,6 +1113,7 @@ static int nfqnl_recv_config(struct net *net, struct sock *ctnl,
 	struct nfqnl_instance *queue;
 	struct nfqnl_msg_config_cmd *cmd = NULL;
 	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
+	__u32 flags = 0, mask = 0;
 	int ret = 0;
 
 	if (nfqa[NFQA_CFG_CMD]) {
@@ -1125,6 +1126,29 @@ static int nfqnl_recv_config(struct net *net, struct sock *ctnl,
 		}
 	}
 
+	/* Check if we support these flags in first place, dependencies should
+	 * be there too not to break atomicity.
+	 */
+	if (nfqa[NFQA_CFG_FLAGS]) {
+		if (!nfqa[NFQA_CFG_MASK]) {
+			/* A mask is needed to specify which flags are being
+			 * changed.
+			 */
+			return -EINVAL;
+		}
+
+		flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS]));
+		mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK]));
+
+		if (flags >= NFQA_CFG_F_MAX)
+			return -EOPNOTSUPP;
+
+#if !IS_ENABLED(CONFIG_NETWORK_SECMARK)
+		if (flags & mask & NFQA_CFG_F_SECCTX)
+			return -EOPNOTSUPP;
+#endif
+	}
+
 	rcu_read_lock();
 	queue = instance_lookup(q, queue_num);
 	if (queue && queue->peer_portid != NETLINK_CB(skb).portid) {
@@ -1162,60 +1186,28 @@ static int nfqnl_recv_config(struct net *net, struct sock *ctnl,
 		}
 	}
 
+	if (!queue) {
+		ret = -ENODEV;
+		goto err_out_unlock;
+	}
+
 	if (nfqa[NFQA_CFG_PARAMS]) {
-		struct nfqnl_msg_config_params *params;
+		struct nfqnl_msg_config_params *params =
+			nla_data(nfqa[NFQA_CFG_PARAMS]);
 
-		if (!queue) {
-			ret = -ENODEV;
-			goto err_out_unlock;
-		}
-		params = nla_data(nfqa[NFQA_CFG_PARAMS]);
 		nfqnl_set_mode(queue, params->copy_mode,
 				ntohl(params->copy_range));
 	}
 
 	if (nfqa[NFQA_CFG_QUEUE_MAXLEN]) {
-		__be32 *queue_maxlen;
+		__be32 *queue_maxlen = nla_data(nfqa[NFQA_CFG_QUEUE_MAXLEN]);
 
-		if (!queue) {
-			ret = -ENODEV;
-			goto err_out_unlock;
-		}
-		queue_maxlen = nla_data(nfqa[NFQA_CFG_QUEUE_MAXLEN]);
 		spin_lock_bh(&queue->lock);
 		queue->queue_maxlen = ntohl(*queue_maxlen);
 		spin_unlock_bh(&queue->lock);
 	}
 
 	if (nfqa[NFQA_CFG_FLAGS]) {
-		__u32 flags, mask;
-
-		if (!queue) {
-			ret = -ENODEV;
-			goto err_out_unlock;
-		}
-
-		if (!nfqa[NFQA_CFG_MASK]) {
-			/* A mask is needed to specify which flags are being
-			 * changed.
-			 */
-			ret = -EINVAL;
-			goto err_out_unlock;
-		}
-
-		flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS]));
-		mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK]));
-
-		if (flags >= NFQA_CFG_F_MAX) {
-			ret = -EOPNOTSUPP;
-			goto err_out_unlock;
-		}
-#if !IS_ENABLED(CONFIG_NETWORK_SECMARK)
-		if (flags & mask & NFQA_CFG_F_SECCTX) {
-			ret = -EOPNOTSUPP;
-			goto err_out_unlock;
-		}
-#endif
 		spin_lock_bh(&queue->lock);
 		queue->flags &= ~mask;
 		queue->flags |= flags & mask;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 11/17] netfilter: nfnetlink_queue: don't handle options after unbind
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (9 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 10/17] netfilter: nfnetlink_queue: validate dependencies to avoid breaking atomicity Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 12/17] netfilter: nfnetlink_queue: just returns error for unknown command Pablo Neira Ayuso
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

From: Ken-ichirou MATSUZAWA <chamaken@gmail.com>

This patch stops processing after destroying a queue instance.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nfnetlink_queue.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index fe360f7..57951ce 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1176,7 +1176,7 @@ static int nfqnl_recv_config(struct net *net, struct sock *ctnl,
 				goto err_out_unlock;
 			}
 			instance_destroy(q, queue);
-			break;
+			goto err_out_unlock;
 		case NFQNL_CFG_CMD_PF_BIND:
 		case NFQNL_CFG_CMD_PF_UNBIND:
 			break;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 12/17] netfilter: nfnetlink_queue: just returns error for unknown command
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (10 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 11/17] netfilter: nfnetlink_queue: don't handle options after unbind Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 13/17] netfilter: nfnetlink_queue: autoload nf_conntrack_netlink module NFQA_CFG_F_CONNTRACK config flag Pablo Neira Ayuso
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

From: Ken-ichirou MATSUZAWA <chamaken@gmail.com>

This patch stops processing options for unknown command.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nfnetlink_queue.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 57951ce..c1f6df4 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1182,7 +1182,7 @@ static int nfqnl_recv_config(struct net *net, struct sock *ctnl,
 			break;
 		default:
 			ret = -ENOTSUPP;
-			break;
+			goto err_out_unlock;
 		}
 	}
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 13/17] netfilter: nfnetlink_queue: autoload nf_conntrack_netlink module NFQA_CFG_F_CONNTRACK config flag
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (11 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 12/17] netfilter: nfnetlink_queue: just returns error for unknown command Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 14/17] netfilter: nfnetlink_log: just returns error for unknown command Pablo Neira Ayuso
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

From: Ken-ichirou MATSUZAWA <chamaken@gmail.com>

This patch enables to load nf_conntrack_netlink module if
NFQA_CFG_F_CONNTRACK config flag is specified.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nfnetlink_queue.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index c1f6df4..1d39365 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1147,6 +1147,17 @@ static int nfqnl_recv_config(struct net *net, struct sock *ctnl,
 		if (flags & mask & NFQA_CFG_F_SECCTX)
 			return -EOPNOTSUPP;
 #endif
+		if ((flags & mask & NFQA_CFG_F_CONNTRACK) &&
+		    !rcu_access_pointer(nfnl_ct_hook)) {
+#ifdef CONFIG_MODULES
+			nfnl_unlock(NFNL_SUBSYS_QUEUE);
+			request_module("ip_conntrack_netlink");
+			nfnl_lock(NFNL_SUBSYS_QUEUE);
+			if (rcu_access_pointer(nfnl_ct_hook))
+				return -EAGAIN;
+#endif
+			return -EOPNOTSUPP;
+		}
 	}
 
 	rcu_read_lock();
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 14/17] netfilter: nfnetlink_log: just returns error for unknown command
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (12 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 13/17] netfilter: nfnetlink_queue: autoload nf_conntrack_netlink module NFQA_CFG_F_CONNTRACK config flag Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 15/17] netfilter: nf_tables: Add new attributes into nft_set to store user data Pablo Neira Ayuso
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

From: Ken-ichirou MATSUZAWA <chamaken@gmail.com>

This patch stops processing options for unknown command.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nfnetlink_log.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 6a57f10..8ca9320 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -888,7 +888,7 @@ static int nfulnl_recv_config(struct net *net, struct sock *ctnl,
 			goto out_put;
 		default:
 			ret = -ENOTSUPP;
-			break;
+			goto out_put;
 		}
 	} else if (!inst) {
 		ret = -ENODEV;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 15/17] netfilter: nf_tables: Add new attributes into nft_set to store user data.
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (13 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 14/17] netfilter: nfnetlink_log: just returns error for unknown command Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:02 ` [PATCH 16/17] netfilter: nft_byteorder: provide 64bit le/be conversion Pablo Neira Ayuso
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

From: Carlos Falgueras García <carlosfg@riseup.net>

User data is stored at after 'nft_set_ops' private data into 'data[]'
flexible array. The field 'udata' points to user data and 'udlen' stores
its length.

Add new flag NFTA_SET_USERDATA.

Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/net/netfilter/nf_tables.h        |  4 ++++
 include/uapi/linux/netfilter/nf_tables.h |  2 ++
 net/netfilter/nf_tables_api.c            | 21 ++++++++++++++++++++-
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 0191fbb..f6b1daf 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -291,6 +291,8 @@ void nft_unregister_set(struct nft_set_ops *ops);
  * 	@timeout: default timeout value in msecs
  * 	@gc_int: garbage collection interval in msecs
  *	@policy: set parameterization (see enum nft_set_policies)
+ *	@udlen: user data length
+ *	@udata: user data
  * 	@ops: set ops
  * 	@pnet: network namespace
  * 	@flags: set flags
@@ -310,6 +312,8 @@ struct nft_set {
 	u64				timeout;
 	u32				gc_int;
 	u16				policy;
+	u16				udlen;
+	unsigned char			*udata;
 	/* runtime data below here */
 	const struct nft_set_ops	*ops ____cacheline_aligned;
 	possible_net_t			pnet;
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 731288a..03c28a4 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -291,6 +291,7 @@ enum nft_set_desc_attributes {
  * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
  * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
  * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
+ * @NFTA_SET_USERDATA: user data (NLA_BINARY)
  */
 enum nft_set_attributes {
 	NFTA_SET_UNSPEC,
@@ -306,6 +307,7 @@ enum nft_set_attributes {
 	NFTA_SET_ID,
 	NFTA_SET_TIMEOUT,
 	NFTA_SET_GC_INTERVAL,
+	NFTA_SET_USERDATA,
 	__NFTA_SET_MAX
 };
 #define NFTA_SET_MAX		(__NFTA_SET_MAX - 1)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index f5c3971..2011977 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2323,6 +2323,8 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
 	[NFTA_SET_ID]			= { .type = NLA_U32 },
 	[NFTA_SET_TIMEOUT]		= { .type = NLA_U64 },
 	[NFTA_SET_GC_INTERVAL]		= { .type = NLA_U32 },
+	[NFTA_SET_USERDATA]		= { .type = NLA_BINARY,
+					    .len  = NFT_USERDATA_MAXLEN },
 };
 
 static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
@@ -2482,6 +2484,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
 			goto nla_put_failure;
 	}
 
+	if (nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
+		goto nla_put_failure;
+
 	desc = nla_nest_start(skb, NFTA_SET_DESC);
 	if (desc == NULL)
 		goto nla_put_failure;
@@ -2691,6 +2696,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
 	u64 timeout;
 	u32 ktype, dtype, flags, policy, gc_int;
 	struct nft_set_desc desc;
+	unsigned char *udata;
+	u16 udlen;
 	int err;
 
 	if (nla[NFTA_SET_TABLE] == NULL ||
@@ -2803,12 +2810,16 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
 	if (IS_ERR(ops))
 		return PTR_ERR(ops);
 
+	udlen = 0;
+	if (nla[NFTA_SET_USERDATA])
+		udlen = nla_len(nla[NFTA_SET_USERDATA]);
+
 	size = 0;
 	if (ops->privsize != NULL)
 		size = ops->privsize(nla);
 
 	err = -ENOMEM;
-	set = kzalloc(sizeof(*set) + size, GFP_KERNEL);
+	set = kzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
 	if (set == NULL)
 		goto err1;
 
@@ -2817,6 +2828,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
 	if (err < 0)
 		goto err2;
 
+	udata = NULL;
+	if (udlen) {
+		udata = set->data + size;
+		nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
+	}
+
 	INIT_LIST_HEAD(&set->bindings);
 	write_pnet(&set->pnet, net);
 	set->ops   = ops;
@@ -2827,6 +2844,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
 	set->flags = flags;
 	set->size  = desc.size;
 	set->policy = policy;
+	set->udlen  = udlen;
+	set->udata  = udata;
 	set->timeout = timeout;
 	set->gc_int = gc_int;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 16/17] netfilter: nft_byteorder: provide 64bit le/be conversion
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (14 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 15/17] netfilter: nf_tables: Add new attributes into nft_set to store user data Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-08 14:26   ` David Laight
  2016-01-08 14:02 ` [PATCH 17/17] netfilter: nft_ct: add byte/packet counter support Pablo Neira Ayuso
  2016-01-09  2:24 ` [PATCH 00/17] Netfilter updates for net-next David Miller
  17 siblings, 1 reply; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

From: Florian Westphal <fw@strlen.de>

Needed to convert the (64bit) conntrack counters to BE ordering.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nft_byteorder.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
index fde5145..383c171 100644
--- a/net/netfilter/nft_byteorder.c
+++ b/net/netfilter/nft_byteorder.c
@@ -8,6 +8,7 @@
  * Development of this code funded by Astaro AG (http://www.astaro.com/)
  */
 
+#include <asm/unaligned.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -39,6 +40,27 @@ static void nft_byteorder_eval(const struct nft_expr *expr,
 	d = (void *)dst;
 
 	switch (priv->size) {
+	case 8: {
+		u64 src64;
+
+		switch (priv->op) {
+		case NFT_BYTEORDER_NTOH:
+			for (i = 0; i < priv->len / 8; i++) {
+				src64 = get_unaligned_be64(&src[i]);
+				src64 = be64_to_cpu((__force __be64)src64);
+				put_unaligned_be64(src64, &dst[i]);
+			}
+			break;
+		case NFT_BYTEORDER_HTON:
+			for (i = 0; i < priv->len / 8; i++) {
+				src64 = get_unaligned_be64(&src[i]);
+				src64 = (__force u64)cpu_to_be64(src64);
+				put_unaligned_be64(src64, &dst[i]);
+			}
+			break;
+		}
+		break;
+	}
 	case 4:
 		switch (priv->op) {
 		case NFT_BYTEORDER_NTOH:
@@ -101,6 +123,7 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
 	switch (priv->size) {
 	case 2:
 	case 4:
+	case 8:
 		break;
 	default:
 		return -EINVAL;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 17/17] netfilter: nft_ct: add byte/packet counter support
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (15 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 16/17] netfilter: nft_byteorder: provide 64bit le/be conversion Pablo Neira Ayuso
@ 2016-01-08 14:02 ` Pablo Neira Ayuso
  2016-01-09  2:24 ` [PATCH 00/17] Netfilter updates for net-next David Miller
  17 siblings, 0 replies; 25+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-08 14:02 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

From: Florian Westphal <fw@strlen.de>

If the accounting extension isn't present, we'll return a counter
value of 0.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/uapi/linux/netfilter/nf_tables.h |  2 ++
 net/netfilter/nft_ct.c                   | 38 ++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 03c28a4..be41ffc 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -757,6 +757,8 @@ enum nft_ct_keys {
 	NFT_CT_PROTO_SRC,
 	NFT_CT_PROTO_DST,
 	NFT_CT_LABELS,
+	NFT_CT_PKTS,
+	NFT_CT_BYTES,
 };
 
 /**
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index 8cbca34..6f74109 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -16,6 +16,7 @@
 #include <linux/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables.h>
 #include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_acct.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
@@ -30,6 +31,18 @@ struct nft_ct {
 	};
 };
 
+static u64 nft_ct_get_eval_counter(const struct nf_conn_counter *c,
+				   enum nft_ct_keys k,
+				   enum ip_conntrack_dir d)
+{
+	if (d < IP_CT_DIR_MAX)
+		return k == NFT_CT_BYTES ? atomic64_read(&c[d].bytes) :
+					   atomic64_read(&c[d].packets);
+
+	return nft_ct_get_eval_counter(c, k, IP_CT_DIR_ORIGINAL) +
+	       nft_ct_get_eval_counter(c, k, IP_CT_DIR_REPLY);
+}
+
 static void nft_ct_get_eval(const struct nft_expr *expr,
 			    struct nft_regs *regs,
 			    const struct nft_pktinfo *pkt)
@@ -114,6 +127,17 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
 			       NF_CT_LABELS_MAX_SIZE - size);
 		return;
 	}
+	case NFT_CT_BYTES: /* fallthrough */
+	case NFT_CT_PKTS: {
+		const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
+		u64 count = 0;
+
+		if (acct)
+			count = nft_ct_get_eval_counter(acct->counter,
+							priv->key, priv->dir);
+		memcpy(dest, &count, sizeof(count));
+		return;
+	}
 #endif
 	default:
 		break;
@@ -291,6 +315,13 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
 			return -EINVAL;
 		len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all);
 		break;
+	case NFT_CT_BYTES:
+	case NFT_CT_PKTS:
+		/* no direction? return sum of original + reply */
+		if (tb[NFTA_CT_DIRECTION] == NULL)
+			priv->dir = IP_CT_DIR_MAX;
+		len = sizeof(u64);
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -373,6 +404,13 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
 	case NFT_CT_PROTO_DST:
 		if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
 			goto nla_put_failure;
+		break;
+	case NFT_CT_BYTES:
+	case NFT_CT_PKTS:
+		if (priv->dir < IP_CT_DIR_MAX &&
+		    nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
+			goto nla_put_failure;
+		break;
 	default:
 		break;
 	}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* RE: [PATCH 16/17] netfilter: nft_byteorder: provide 64bit le/be conversion
  2016-01-08 14:02 ` [PATCH 16/17] netfilter: nft_byteorder: provide 64bit le/be conversion Pablo Neira Ayuso
@ 2016-01-08 14:26   ` David Laight
  2016-01-08 16:23     ` Florian Westphal
  0 siblings, 1 reply; 25+ messages in thread
From: David Laight @ 2016-01-08 14:26 UTC (permalink / raw)
  To: 'Pablo Neira Ayuso', netfilter-devel; +Cc: davem, netdev

From: Pablo Neira Ayuso
> Sent: 08 January 2016 14:02
> From: Florian Westphal <fw@strlen.de>
> 
> Needed to convert the (64bit) conntrack counters to BE ordering.
> 
...
>  	switch (priv->size) {
> +	case 8: {
> +		u64 src64;
> +
> +		switch (priv->op) {
> +		case NFT_BYTEORDER_NTOH:
> +			for (i = 0; i < priv->len / 8; i++) {
> +				src64 = get_unaligned_be64(&src[i]);
> +				src64 = be64_to_cpu((__force __be64)src64);
> +				put_unaligned_be64(src64, &dst[i]);
> +			}
> +			break;
> +		case NFT_BYTEORDER_HTON:
> +			for (i = 0; i < priv->len / 8; i++) {
> +				src64 = get_unaligned_be64(&src[i]);
> +				src64 = (__force u64)cpu_to_be64(src64);
> +				put_unaligned_be64(src64, &dst[i]);
> +			}
> +			break;
> +		}
> +		break;

That is horrid.
On a little-endian system you are byteswapping the data 3 times.
Image the code on a cpu that doesn't support misaligned transfers
and doesn't have a byteswap instruction.

	David

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 16/17] netfilter: nft_byteorder: provide 64bit le/be conversion
  2016-01-08 14:26   ` David Laight
@ 2016-01-08 16:23     ` Florian Westphal
  2016-01-08 16:41       ` David Laight
  0 siblings, 1 reply; 25+ messages in thread
From: Florian Westphal @ 2016-01-08 16:23 UTC (permalink / raw)
  To: David Laight; +Cc: 'Pablo Neira Ayuso', netfilter-devel, davem, netdev

David Laight <David.Laight@ACULAB.COM> wrote:
> From: Pablo Neira Ayuso
> > Sent: 08 January 2016 14:02
> > From: Florian Westphal <fw@strlen.de>
> > 
> > Needed to convert the (64bit) conntrack counters to BE ordering.
> > 
> ...
> >  	switch (priv->size) {
> > +	case 8: {
> > +		u64 src64;
> > +
> > +		switch (priv->op) {
> > +		case NFT_BYTEORDER_NTOH:
> > +			for (i = 0; i < priv->len / 8; i++) {
> > +				src64 = get_unaligned_be64(&src[i]);
> > +				src64 = be64_to_cpu((__force __be64)src64);
> > +				put_unaligned_be64(src64, &dst[i]);
> > +			}
> > +			break;
> > +		case NFT_BYTEORDER_HTON:
> > +			for (i = 0; i < priv->len / 8; i++) {
> > +				src64 = get_unaligned_be64(&src[i]);
> > +				src64 = (__force u64)cpu_to_be64(src64);
> > +				put_unaligned_be64(src64, &dst[i]);
> > +			}
> > +			break;
> > +		}
> > +		break;
> 
> That is horrid.

Yes, sorry for this, however ...

> On a little-endian system you are byteswapping the data 3 times.
> Image the code on a cpu that doesn't support misaligned transfers
> and doesn't have a byteswap instruction.

diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
--- a/net/netfilter/nft_byteorder.c
+++ b/net/netfilter/nft_byteorder.c
@@ -46,16 +46,16 @@ static void nft_byteorder_eval(const struct nft_expr *expr,
 		switch (priv->op) {
 		case NFT_BYTEORDER_NTOH:
 			for (i = 0; i < priv->len / 8; i++) {
-				src64 = get_unaligned_be64(&src[i]);
+				src64 = get_unaligned((u64 *)&src[i]);
 				src64 = be64_to_cpu((__force __be64)src64);
-				put_unaligned_be64(src64, &dst[i]);
+				put_unaligned(src64, (u64 *)&dst[i]);
 			}
 			break;
 		case NFT_BYTEORDER_HTON:
 			for (i = 0; i < priv->len / 8; i++) {
-				src64 = get_unaligned_be64(&src[i]);
+				src64 = get_unaligned((u64 *)&src[i]);
 				src64 = (__force u64)cpu_to_be64(src64);
-				put_unaligned_be64(src64, &dst[i]);
+				put_unaligned(src64, (u64 *)&dst[i]);
 			}
 			break;
 		}

Results in identical object code.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: [PATCH 16/17] netfilter: nft_byteorder: provide 64bit le/be conversion
  2016-01-08 16:23     ` Florian Westphal
@ 2016-01-08 16:41       ` David Laight
  2016-01-08 16:55         ` Florian Westphal
  0 siblings, 1 reply; 25+ messages in thread
From: David Laight @ 2016-01-08 16:41 UTC (permalink / raw)
  To: 'Florian Westphal'
  Cc: 'Pablo Neira Ayuso', netfilter-devel, davem, netdev

From: Florian Westphal
> Sent: 08 January 2016 16:24
> To: David Laight
> David Laight <David.Laight@ACULAB.COM> wrote:
> > From: Pablo Neira Ayuso
> > > Sent: 08 January 2016 14:02
> > > From: Florian Westphal <fw@strlen.de>
> > >
> > > Needed to convert the (64bit) conntrack counters to BE ordering.
> > >
> > ...
> > >  	switch (priv->size) {
> > > +	case 8: {
> > > +		u64 src64;
> > > +
> > > +		switch (priv->op) {
> > > +		case NFT_BYTEORDER_NTOH:
> > > +			for (i = 0; i < priv->len / 8; i++) {
> > > +				src64 = get_unaligned_be64(&src[i]);
> > > +				src64 = be64_to_cpu((__force __be64)src64);
> > > +				put_unaligned_be64(src64, &dst[i]);
> > > +			}
> > > +			break;
> > > +		case NFT_BYTEORDER_HTON:
> > > +			for (i = 0; i < priv->len / 8; i++) {
> > > +				src64 = get_unaligned_be64(&src[i]);
> > > +				src64 = (__force u64)cpu_to_be64(src64);
> > > +				put_unaligned_be64(src64, &dst[i]);
> > > +			}
> > > +			break;
> > > +		}
> > > +		break;
> >
> > That is horrid.
> 
> Yes, sorry for this, however ...
> 
> > On a little-endian system you are byteswapping the data 3 times.
> > Image the code on a cpu that doesn't support misaligned transfers
> > and doesn't have a byteswap instruction.
> 
> diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
> --- a/net/netfilter/nft_byteorder.c
> +++ b/net/netfilter/nft_byteorder.c
> @@ -46,16 +46,16 @@ static void nft_byteorder_eval(const struct nft_expr *expr,
>  		switch (priv->op) {
>  		case NFT_BYTEORDER_NTOH:
>  			for (i = 0; i < priv->len / 8; i++) {
> -				src64 = get_unaligned_be64(&src[i]);
> +				src64 = get_unaligned((u64 *)&src[i]);
>  				src64 = be64_to_cpu((__force __be64)src64);
> -				put_unaligned_be64(src64, &dst[i]);
> +				put_unaligned(src64, (u64 *)&dst[i]);

Why not just:
				src64 = get_unaligned_be64(&src[i]);
				put_unaligned(src64, (u64 *)&dst[i]);

...
> Results in identical object code.

How many architectures have you looked at?
Try sparc64, ppc64 and arm64, especially le variants.
(le sparc would be bad - but doesn't exist).
Also older compilers that don't have builtin support for misaligned
memory accesses.

Actually there is (probably) a generic problem with:
		put_unaligned(src64, (u64 *)&dst[i]);
The C language rules for casts effectively forbid pointers to
misaligned structures (the compiler is allowed to assume they
are aligned however hard you try to persuade it otherwise).
I suspect that means that the (u64 *) cast is allowed to mask
off the bottom address bits.

	David


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 16/17] netfilter: nft_byteorder: provide 64bit le/be conversion
  2016-01-08 16:41       ` David Laight
@ 2016-01-08 16:55         ` Florian Westphal
  0 siblings, 0 replies; 25+ messages in thread
From: Florian Westphal @ 2016-01-08 16:55 UTC (permalink / raw)
  To: David Laight
  Cc: 'Florian Westphal', 'Pablo Neira Ayuso',
	netfilter-devel, davem, netdev

David Laight <David.Laight@ACULAB.COM> wrote:
> From: Florian Westphal
> > Sent: 08 January 2016 16:24
> > To: David Laight
> > David Laight <David.Laight@ACULAB.COM> wrote:
> > > From: Pablo Neira Ayuso
> > > > Sent: 08 January 2016 14:02
> > > > From: Florian Westphal <fw@strlen.de>
> > > >
> > > > Needed to convert the (64bit) conntrack counters to BE ordering.
> > > >
> > > ...
> > > >  	switch (priv->size) {
> > > > +	case 8: {
> > > > +		u64 src64;
> > > > +
> > > > +		switch (priv->op) {
> > > > +		case NFT_BYTEORDER_NTOH:
> > > > +			for (i = 0; i < priv->len / 8; i++) {
> > > > +				src64 = get_unaligned_be64(&src[i]);
> > > > +				src64 = be64_to_cpu((__force __be64)src64);
> > > > +				put_unaligned_be64(src64, &dst[i]);
> > > > +			}
> > > > +			break;
> > > > +		case NFT_BYTEORDER_HTON:
> > > > +			for (i = 0; i < priv->len / 8; i++) {
> > > > +				src64 = get_unaligned_be64(&src[i]);
> > > > +				src64 = (__force u64)cpu_to_be64(src64);
> > > > +				put_unaligned_be64(src64, &dst[i]);
> > > > +			}
> > > > +			break;
> > > > +		}
> > > > +		break;
> > >
> > > That is horrid.
> > 
> > Yes, sorry for this, however ...
> > 
> > > On a little-endian system you are byteswapping the data 3 times.
> > > Image the code on a cpu that doesn't support misaligned transfers
> > > and doesn't have a byteswap instruction.
> > 
> > diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
> > --- a/net/netfilter/nft_byteorder.c
> > +++ b/net/netfilter/nft_byteorder.c
> > @@ -46,16 +46,16 @@ static void nft_byteorder_eval(const struct nft_expr *expr,
> >  		switch (priv->op) {
> >  		case NFT_BYTEORDER_NTOH:
> >  			for (i = 0; i < priv->len / 8; i++) {
> > -				src64 = get_unaligned_be64(&src[i]);
> > +				src64 = get_unaligned((u64 *)&src[i]);
> >  				src64 = be64_to_cpu((__force __be64)src64);
> > -				put_unaligned_be64(src64, &dst[i]);
> > +				put_unaligned(src64, (u64 *)&dst[i]);
> 
> Why not just:
> 				src64 = get_unaligned_be64(&src[i]);
> 				put_unaligned(src64, (u64 *)&dst[i]);

Sure.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 00/17] Netfilter updates for net-next
  2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
                   ` (16 preceding siblings ...)
  2016-01-08 14:02 ` [PATCH 17/17] netfilter: nft_ct: add byte/packet counter support Pablo Neira Ayuso
@ 2016-01-09  2:24 ` David Miller
  17 siblings, 0 replies; 25+ messages in thread
From: David Miller @ 2016-01-09  2:24 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, netdev

From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Fri,  8 Jan 2016 15:02:00 +0100

> The following patchset contains Netfilter updates for net-next, they are:

I'll pull this, but please follow-up wrt. the endianness conversion
changes.

Thanks.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 00/17] Netfilter updates for net-next
  2019-12-30 11:21 Pablo Neira Ayuso
@ 2019-12-30 22:29 ` David Miller
  0 siblings, 0 replies; 25+ messages in thread
From: David Miller @ 2019-12-30 22:29 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, netdev

From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Mon, 30 Dec 2019 12:21:26 +0100

> The following patchset contains Netfilter updates for net-next:
 ...
> This batch, among other things, contains updates for the netfilter
> tunnel netlink interface: This extension is still incomplete and lacking
> proper userspace support which is actually my fault, I did not find the
> time to go back and finish this. This update is breaking tunnel UAPI in
> some aspects to fix it but do it better sooner than never.
> 
> You can pull these changes from:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git

Pulled, thanks Pablo.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 00/17] Netfilter updates for net-next
@ 2019-12-30 11:21 Pablo Neira Ayuso
  2019-12-30 22:29 ` David Miller
  0 siblings, 1 reply; 25+ messages in thread
From: Pablo Neira Ayuso @ 2019-12-30 11:21 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

Hi,

The following patchset contains Netfilter updates for net-next:

1) Remove #ifdef pollution around nf_ingress(), from Lukas Wunner.

2) Document ingress hook in netdevice, also from Lukas.

3) Remove htons() in tunnel metadata port netlink attributes,
   from Xin Long.

4) Missing erspan netlink attribute validation also from Xin Long.

5) Missing erspan version in tunnel, from Xin Long.

6) Missing attribute nest in NFTA_TUNNEL_KEY_OPTS_{VXLAN,ERSPAN}
   Patch from Xin Long.

7) Missing nla_nest_cancel() in tunnel netlink dump path,
   from Xin Long.

8) Remove two exported conntrack symbols with no clients,
   from Florian Westphal.

9) Add nft_meta_get_eval_time() helper to nft_meta, from Florian.

10) Add nft_meta_pkttype helper for loopback, also from Florian.

11) Add nft_meta_socket uid helper, from Florian Westphal.

12) Add nft_meta_cgroup helper, from Florian.

13) Add nft_meta_ifkind helper, from Florian.

14) Group all interface related meta selector, from Florian.

15) Add nft_prandom_u32() helper, from Florian.

16) Add nft_meta_rtclassid helper, from Florian.

17) Add support for matching on the slave device index,
    from Florian.

This batch, among other things, contains updates for the netfilter
tunnel netlink interface: This extension is still incomplete and lacking
proper userspace support which is actually my fault, I did not find the
time to go back and finish this. This update is breaking tunnel UAPI in
some aspects to fix it but do it better sooner than never.

You can pull these changes from:

  git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git

Thank you.

----------------------------------------------------------------

The following changes since commit 6f6dded1385cfb564de85f86126f1c054c8f47b1:

  Merge branch 'WireGuard-CI-and-housekeeping' (2019-12-16 19:22:22 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git HEAD

for you to fetch changes up to c14ceb0ec727187f71a487a592ffa91767fed66e:

  netfilter: nft_meta: add support for slave device ifindex matching (2019-12-26 17:41:34 +0100)

----------------------------------------------------------------
Florian Westphal (10):
      netfilter: conntrack: remove two export symbols
      netfilter: nft_meta: move time handling to helper
      netfilter: nft_meta: move pkttype handling to helper
      netfilter: nft_meta: move sk uid/git handling to helper
      netfilter: nft_meta: move cgroup handling to helper
      netfilter: nft_meta: move interface kind handling to helper
      netfilter: nft_meta: move all interface related keys to helper
      netfilter: nft_meta: place prandom handling in a helper
      netfilter: nft_meta: place rtclassid handling in a helper
      netfilter: nft_meta: add support for slave device ifindex matching

Lukas Wunner (2):
      netfilter: Clean up unnecessary #ifdef
      netfilter: Document ingress hook

Xin Long (5):
      netfilter: nft_tunnel: no need to call htons() when dumping ports
      netfilter: nft_tunnel: add the missing ERSPAN_VERSION nla_policy
      netfilter: nft_tunnel: also dump ERSPAN_VERSION
      netfilter: nft_tunnel: also dump OPTS_ERSPAN/VXLAN
      netfilter: nft_tunnel: add the missing nla_nest_cancel()

 include/linux/netdevice.h                |   1 +
 include/uapi/linux/netfilter/nf_tables.h |   4 +
 net/core/dev.c                           |   2 -
 net/netfilter/nf_conntrack_core.c        |   1 -
 net/netfilter/nf_conntrack_extend.c      |   1 -
 net/netfilter/nft_meta.c                 | 440 ++++++++++++++++++++++---------
 net/netfilter/nft_tunnel.c               |  52 +++-
 7 files changed, 357 insertions(+), 144 deletions(-)

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2019-12-30 22:29 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-08 14:02 [PATCH 00/17] Netfilter updates for net-next Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 01/17] netfilter: nf_tables: release objects on netns destruction Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 02/17] netfilter: nf_tables: destroy basechain and rules on netdevice removal Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 03/17] netfilter: nf_tables: remove check against removal of inactive objects Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 04/17] netfilter: nfnetlink: pass down netns pointer to call() and call_rcu() Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 05/17] netfilter: nfnetlink: pass down netns pointer to commit() and abort() callbacks Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 06/17] netfilter: nft_limit: allow to invert matching criteria Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 07/17] netfilter: nf_tables: add packet duplication to the netdev family Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 08/17] netfilter: nf_tables: add forward expression " Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 09/17] netfilter: nf_ct_helper: define pr_fmt() Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 10/17] netfilter: nfnetlink_queue: validate dependencies to avoid breaking atomicity Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 11/17] netfilter: nfnetlink_queue: don't handle options after unbind Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 12/17] netfilter: nfnetlink_queue: just returns error for unknown command Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 13/17] netfilter: nfnetlink_queue: autoload nf_conntrack_netlink module NFQA_CFG_F_CONNTRACK config flag Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 14/17] netfilter: nfnetlink_log: just returns error for unknown command Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 15/17] netfilter: nf_tables: Add new attributes into nft_set to store user data Pablo Neira Ayuso
2016-01-08 14:02 ` [PATCH 16/17] netfilter: nft_byteorder: provide 64bit le/be conversion Pablo Neira Ayuso
2016-01-08 14:26   ` David Laight
2016-01-08 16:23     ` Florian Westphal
2016-01-08 16:41       ` David Laight
2016-01-08 16:55         ` Florian Westphal
2016-01-08 14:02 ` [PATCH 17/17] netfilter: nft_ct: add byte/packet counter support Pablo Neira Ayuso
2016-01-09  2:24 ` [PATCH 00/17] Netfilter updates for net-next David Miller
2019-12-30 11:21 Pablo Neira Ayuso
2019-12-30 22:29 ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.