netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nf-next 0/2] netfilter: nfnetlink_log attach conntrack
@ 2015-08-24 23:10 Ken-ichirou MATSUZAWA
  2015-08-24 23:13 ` [PATCH nf-next 1/2] netfilter: nfnetlink_queue: enable to specify nla type Ken-ichirou MATSUZAWA
  2015-08-24 23:15 ` [PATCH nf-next 2/2] netfilter: nfnetlink_log: allow to attach conntrack Ken-ichirou MATSUZAWA
  0 siblings, 2 replies; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-08-24 23:10 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

 Hi,
 
 It would be good if conntrack information is attached to nflog
netlink message since we can get NATed information from nflog. This
patch series uses NFQUEUE basis in a hacky way, could it be
acceptable?

Thanks,
Ken

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

* [PATCH nf-next 1/2] netfilter: nfnetlink_queue: enable to specify nla type
  2015-08-24 23:10 [PATCH nf-next 0/2] netfilter: nfnetlink_log attach conntrack Ken-ichirou MATSUZAWA
@ 2015-08-24 23:13 ` Ken-ichirou MATSUZAWA
  2015-08-24 23:15 ` [PATCH nf-next 2/2] netfilter: nfnetlink_log: allow to attach conntrack Ken-ichirou MATSUZAWA
  1 sibling, 0 replies; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-08-24 23:13 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

This patch updates nfqnl_ct_put() signature to put not only queue
related attribute type.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
---
 include/net/netfilter/nfnetlink_queue.h |    8 +++++---
 net/netfilter/nfnetlink_queue_core.c    |    2 +-
 net/netfilter/nfnetlink_queue_ct.c      |    9 +++++----
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h
index aff88ba..f94942b 100644
--- a/include/net/netfilter/nfnetlink_queue.h
+++ b/include/net/netfilter/nfnetlink_queue.h
@@ -11,8 +11,9 @@ struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
 struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
 			       const struct nlattr *attr,
 			       enum ip_conntrack_info *ctinfo);
-int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
-		 enum ip_conntrack_info ctinfo);
+int nfqnl_ct_put(struct sk_buff *skb,
+		 struct nf_conn *ct, int type,
+		 enum ip_conntrack_info ctinfo, int info_type);
 void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
 			 enum ip_conntrack_info ctinfo, int diff);
 int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
@@ -32,7 +33,8 @@ inline struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
 }
 
 inline int
-nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, int type,
+	     enum ip_conntrack_info ctinfo, int info_type)
 {
 	return 0;
 }
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 685cc6a..283a189 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -507,7 +507,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
 	if (seclen && nla_put(skb, NFQA_SECCTX, seclen, secdata))
 		goto nla_put_failure;
 
-	if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
+	if (ct && nfqnl_ct_put(skb, ct, NFQA_CT, ctinfo, NFQA_CT_INFO) < 0)
 		goto nla_put_failure;
 
 	if (cap_len > data_len &&
diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c
index 96cac50..2a30618 100644
--- a/net/netfilter/nfnetlink_queue_ct.c
+++ b/net/netfilter/nfnetlink_queue_ct.c
@@ -54,8 +54,9 @@ nfqnl_ct_parse(const struct sk_buff *skb, const struct nlattr *attr,
 	return ct;
 }
 
-int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
-		 enum ip_conntrack_info ctinfo)
+int nfqnl_ct_put(struct sk_buff *skb,
+		 struct nf_conn *ct, int type,
+		 enum ip_conntrack_info ctinfo, int info_type)
 {
 	struct nfq_ct_hook *nfq_ct;
 	struct nlattr *nest_parms;
@@ -65,7 +66,7 @@ int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
 	if (nfq_ct == NULL)
 		return 0;
 
-	nest_parms = nla_nest_start(skb, NFQA_CT | NLA_F_NESTED);
+	nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
 	if (!nest_parms)
 		goto nla_put_failure;
 
@@ -75,7 +76,7 @@ int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
 	nla_nest_end(skb, nest_parms);
 
 	tmp = ctinfo;
-	if (nla_put_be32(skb, NFQA_CT_INFO, htonl(tmp)))
+	if (nla_put_be32(skb, info_type, htonl(tmp)))
 		goto nla_put_failure;
 
 	return 0;
-- 
1.7.10.4


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

* [PATCH nf-next 2/2] netfilter: nfnetlink_log: allow to attach conntrack
  2015-08-24 23:10 [PATCH nf-next 0/2] netfilter: nfnetlink_log attach conntrack Ken-ichirou MATSUZAWA
  2015-08-24 23:13 ` [PATCH nf-next 1/2] netfilter: nfnetlink_queue: enable to specify nla type Ken-ichirou MATSUZAWA
@ 2015-08-24 23:15 ` Ken-ichirou MATSUZAWA
  2015-08-26 19:05   ` Pablo Neira Ayuso
  1 sibling, 1 reply; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-08-24 23:15 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

This patch enables to include the conntrack information together
with the packet that is sent to user-space via NFLOG, then a
user-space program can acquire NATed information by this NFULA_CT
attribute.

Including the conntrack information is optional, you can set it
via NFULNL_CFG_F_CONNTRACK flag with the NFULA_CFG_FLAGS attribute
like NFQUEUE.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
---
 include/net/netfilter/nfnetlink_queue.h      |    4 +-
 include/uapi/linux/netfilter/nfnetlink_log.h |    3 +
 net/netfilter/Kconfig                        |    9 +-
 net/netfilter/Makefile                       |    2 +
 net/netfilter/nfnetlink_log.c                | 1123 -------------------------
 net/netfilter/nfnetlink_log_core.c           | 1135 ++++++++++++++++++++++++++
 net/netfilter/nfnetlink_queue_ct.c           |    2 +-
 7 files changed, 1148 insertions(+), 1130 deletions(-)
 delete mode 100644 net/netfilter/nfnetlink_log.c
 create mode 100644 net/netfilter/nfnetlink_log_core.c

diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h
index f94942b..05315ab 100644
--- a/include/net/netfilter/nfnetlink_queue.h
+++ b/include/net/netfilter/nfnetlink_queue.h
@@ -6,7 +6,7 @@
 struct nf_conn;
 
 #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
-struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
+struct nf_conn *nfqnl_ct_get(const struct sk_buff *entskb, size_t *size,
 			     enum ip_conntrack_info *ctinfo);
 struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
 			       const struct nlattr *attr,
@@ -20,7 +20,7 @@ int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
 			u32 portid, u32 report);
 #else
 inline struct nf_conn *
-nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
+nfqnl_ct_get(const struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
 {
 	return NULL;
 }
diff --git a/include/uapi/linux/netfilter/nfnetlink_log.h b/include/uapi/linux/netfilter/nfnetlink_log.h
index 90c2c95..081e7f9 100644
--- a/include/uapi/linux/netfilter/nfnetlink_log.h
+++ b/include/uapi/linux/netfilter/nfnetlink_log.h
@@ -51,6 +51,8 @@ enum nfulnl_attr_type {
 	NFULA_HWTYPE,			/* hardware type */
 	NFULA_HWHEADER,			/* hardware header */
 	NFULA_HWLEN,			/* hardware header length */
+	NFULA_CT,			/* nf_conntrack_netlink.h */
+	NFULA_CT_INFO,			/* enum ip_conntrack_info */
 
 	__NFULA_MAX
 };
@@ -93,5 +95,6 @@ enum nfulnl_attr_config {
 
 #define NFULNL_CFG_F_SEQ	0x0001
 #define NFULNL_CFG_F_SEQ_GLOBAL	0x0002
+#define NFULNL_CFG_F_CONNTRACK	0x0004
 
 #endif /* _NFNETLINK_LOG_H */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3e1b4ab..b3db079 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -363,12 +363,13 @@ config NF_CT_NETLINK_HELPER
 	  If unsure, say `N'.
 
 config NETFILTER_NETLINK_QUEUE_CT
-        bool "NFQUEUE integration with Connection Tracking"
+        bool "NFQUEUE/NFLOG integration with Connection Tracking"
         default n
-        depends on NETFILTER_NETLINK_QUEUE
+        depends on NETFILTER_NETLINK_QUEUE || NETFILTER_NETLINK_LOG
 	help
-	  If this option is enabled, NFQUEUE can include Connection Tracking
-	  information together with the packet is the enqueued via NFNETLINK.
+	  If this option is enabled, NFQUEUE and/or NFLOG can include
+	  Connection Tracking information together with the packet is
+	  enqueued, logged via NFNETLINK.
 
 config NF_NAT
 	tristate
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 70d026d..3657898 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -13,6 +13,8 @@ obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o
 nfnetlink_queue-y := nfnetlink_queue_core.o
 nfnetlink_queue-$(CONFIG_NETFILTER_NETLINK_QUEUE_CT) += nfnetlink_queue_ct.o
 obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
+nfnetlink_log-y := nfnetlink_log_core.o
+nfnetlink_log-$(CONFIG_NETFILTER_NETLINK_QUEUE_CT) += nfnetlink_queue_ct.o
 obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
 
 # connection tracking
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
deleted file mode 100644
index 4670821..0000000
--- a/net/netfilter/nfnetlink_log.c
+++ /dev/null
@@ -1,1123 +0,0 @@
-/*
- * This is a module which is used for logging packets to userspace via
- * nfetlink.
- *
- * (C) 2005 by Harald Welte <laforge@netfilter.org>
- * (C) 2006-2012 Patrick McHardy <kaber@trash.net>
- *
- * Based on the old ipv4-only ipt_ULOG.c:
- * (C) 2000-2004 by Harald Welte <laforge@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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/init.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/netdevice.h>
-#include <linux/netfilter.h>
-#include <linux/netfilter_bridge.h>
-#include <net/netlink.h>
-#include <linux/netfilter/nfnetlink.h>
-#include <linux/netfilter/nfnetlink_log.h>
-#include <linux/spinlock.h>
-#include <linux/sysctl.h>
-#include <linux/proc_fs.h>
-#include <linux/security.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <net/sock.h>
-#include <net/netfilter/nf_log.h>
-#include <net/netns/generic.h>
-#include <net/netfilter/nfnetlink_log.h>
-
-#include <linux/atomic.h>
-
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-#include "../bridge/br_private.h"
-#endif
-
-#define NFULNL_NLBUFSIZ_DEFAULT	NLMSG_GOODSIZE
-#define NFULNL_TIMEOUT_DEFAULT 	100	/* every second */
-#define NFULNL_QTHRESH_DEFAULT 	100	/* 100 packets */
-/* max packet size is limited by 16-bit struct nfattr nfa_len field */
-#define NFULNL_COPY_RANGE_MAX	(0xFFFF - NLA_HDRLEN)
-
-#define PRINTR(x, args...)	do { if (net_ratelimit()) \
-				     printk(x, ## args); } while (0);
-
-struct nfulnl_instance {
-	struct hlist_node hlist;	/* global list of instances */
-	spinlock_t lock;
-	atomic_t use;			/* use count */
-
-	unsigned int qlen;		/* number of nlmsgs in skb */
-	struct sk_buff *skb;		/* pre-allocatd skb */
-	struct timer_list timer;
-	struct net *net;
-	struct user_namespace *peer_user_ns;	/* User namespace of the peer process */
-	u32 peer_portid;		/* PORTID of the peer process */
-
-	/* configurable parameters */
-	unsigned int flushtimeout;	/* timeout until queue flush */
-	unsigned int nlbufsiz;		/* netlink buffer allocation size */
-	unsigned int qthreshold;	/* threshold of the queue */
-	u_int32_t copy_range;
-	u_int32_t seq;			/* instance-local sequential counter */
-	u_int16_t group_num;		/* number of this queue */
-	u_int16_t flags;
-	u_int8_t copy_mode;
-	struct rcu_head rcu;
-};
-
-#define INSTANCE_BUCKETS	16
-
-static int nfnl_log_net_id __read_mostly;
-
-struct nfnl_log_net {
-	spinlock_t instances_lock;
-	struct hlist_head instance_table[INSTANCE_BUCKETS];
-	atomic_t global_seq;
-};
-
-static struct nfnl_log_net *nfnl_log_pernet(struct net *net)
-{
-	return net_generic(net, nfnl_log_net_id);
-}
-
-static inline u_int8_t instance_hashfn(u_int16_t group_num)
-{
-	return ((group_num & 0xff) % INSTANCE_BUCKETS);
-}
-
-static struct nfulnl_instance *
-__instance_lookup(struct nfnl_log_net *log, u_int16_t group_num)
-{
-	struct hlist_head *head;
-	struct nfulnl_instance *inst;
-
-	head = &log->instance_table[instance_hashfn(group_num)];
-	hlist_for_each_entry_rcu(inst, head, hlist) {
-		if (inst->group_num == group_num)
-			return inst;
-	}
-	return NULL;
-}
-
-static inline void
-instance_get(struct nfulnl_instance *inst)
-{
-	atomic_inc(&inst->use);
-}
-
-static struct nfulnl_instance *
-instance_lookup_get(struct nfnl_log_net *log, u_int16_t group_num)
-{
-	struct nfulnl_instance *inst;
-
-	rcu_read_lock_bh();
-	inst = __instance_lookup(log, group_num);
-	if (inst && !atomic_inc_not_zero(&inst->use))
-		inst = NULL;
-	rcu_read_unlock_bh();
-
-	return inst;
-}
-
-static void nfulnl_instance_free_rcu(struct rcu_head *head)
-{
-	struct nfulnl_instance *inst =
-		container_of(head, struct nfulnl_instance, rcu);
-
-	put_net(inst->net);
-	kfree(inst);
-	module_put(THIS_MODULE);
-}
-
-static void
-instance_put(struct nfulnl_instance *inst)
-{
-	if (inst && atomic_dec_and_test(&inst->use))
-		call_rcu_bh(&inst->rcu, nfulnl_instance_free_rcu);
-}
-
-static void nfulnl_timer(unsigned long data);
-
-static struct nfulnl_instance *
-instance_create(struct net *net, u_int16_t group_num,
-		u32 portid, struct user_namespace *user_ns)
-{
-	struct nfulnl_instance *inst;
-	struct nfnl_log_net *log = nfnl_log_pernet(net);
-	int err;
-
-	spin_lock_bh(&log->instances_lock);
-	if (__instance_lookup(log, group_num)) {
-		err = -EEXIST;
-		goto out_unlock;
-	}
-
-	inst = kzalloc(sizeof(*inst), GFP_ATOMIC);
-	if (!inst) {
-		err = -ENOMEM;
-		goto out_unlock;
-	}
-
-	if (!try_module_get(THIS_MODULE)) {
-		kfree(inst);
-		err = -EAGAIN;
-		goto out_unlock;
-	}
-
-	INIT_HLIST_NODE(&inst->hlist);
-	spin_lock_init(&inst->lock);
-	/* needs to be two, since we _put() after creation */
-	atomic_set(&inst->use, 2);
-
-	setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst);
-
-	inst->net = get_net(net);
-	inst->peer_user_ns = user_ns;
-	inst->peer_portid = portid;
-	inst->group_num = group_num;
-
-	inst->qthreshold 	= NFULNL_QTHRESH_DEFAULT;
-	inst->flushtimeout 	= NFULNL_TIMEOUT_DEFAULT;
-	inst->nlbufsiz 		= NFULNL_NLBUFSIZ_DEFAULT;
-	inst->copy_mode 	= NFULNL_COPY_PACKET;
-	inst->copy_range 	= NFULNL_COPY_RANGE_MAX;
-
-	hlist_add_head_rcu(&inst->hlist,
-		       &log->instance_table[instance_hashfn(group_num)]);
-
-
-	spin_unlock_bh(&log->instances_lock);
-
-	return inst;
-
-out_unlock:
-	spin_unlock_bh(&log->instances_lock);
-	return ERR_PTR(err);
-}
-
-static void __nfulnl_flush(struct nfulnl_instance *inst);
-
-/* called with BH disabled */
-static void
-__instance_destroy(struct nfulnl_instance *inst)
-{
-	/* first pull it out of the global list */
-	hlist_del_rcu(&inst->hlist);
-
-	/* then flush all pending packets from skb */
-
-	spin_lock(&inst->lock);
-
-	/* lockless readers wont be able to use us */
-	inst->copy_mode = NFULNL_COPY_DISABLED;
-
-	if (inst->skb)
-		__nfulnl_flush(inst);
-	spin_unlock(&inst->lock);
-
-	/* and finally put the refcount */
-	instance_put(inst);
-}
-
-static inline void
-instance_destroy(struct nfnl_log_net *log,
-		 struct nfulnl_instance *inst)
-{
-	spin_lock_bh(&log->instances_lock);
-	__instance_destroy(inst);
-	spin_unlock_bh(&log->instances_lock);
-}
-
-static int
-nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
-		  unsigned int range)
-{
-	int status = 0;
-
-	spin_lock_bh(&inst->lock);
-
-	switch (mode) {
-	case NFULNL_COPY_NONE:
-	case NFULNL_COPY_META:
-		inst->copy_mode = mode;
-		inst->copy_range = 0;
-		break;
-
-	case NFULNL_COPY_PACKET:
-		inst->copy_mode = mode;
-		if (range == 0)
-			range = NFULNL_COPY_RANGE_MAX;
-		inst->copy_range = min_t(unsigned int,
-					 range, NFULNL_COPY_RANGE_MAX);
-		break;
-
-	default:
-		status = -EINVAL;
-		break;
-	}
-
-	spin_unlock_bh(&inst->lock);
-
-	return status;
-}
-
-static int
-nfulnl_set_nlbufsiz(struct nfulnl_instance *inst, u_int32_t nlbufsiz)
-{
-	int status;
-
-	spin_lock_bh(&inst->lock);
-	if (nlbufsiz < NFULNL_NLBUFSIZ_DEFAULT)
-		status = -ERANGE;
-	else if (nlbufsiz > 131072)
-		status = -ERANGE;
-	else {
-		inst->nlbufsiz = nlbufsiz;
-		status = 0;
-	}
-	spin_unlock_bh(&inst->lock);
-
-	return status;
-}
-
-static int
-nfulnl_set_timeout(struct nfulnl_instance *inst, u_int32_t timeout)
-{
-	spin_lock_bh(&inst->lock);
-	inst->flushtimeout = timeout;
-	spin_unlock_bh(&inst->lock);
-
-	return 0;
-}
-
-static int
-nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh)
-{
-	spin_lock_bh(&inst->lock);
-	inst->qthreshold = qthresh;
-	spin_unlock_bh(&inst->lock);
-
-	return 0;
-}
-
-static int
-nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags)
-{
-	spin_lock_bh(&inst->lock);
-	inst->flags = flags;
-	spin_unlock_bh(&inst->lock);
-
-	return 0;
-}
-
-static struct sk_buff *
-nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
-		 unsigned int pkt_size)
-{
-	struct sk_buff *skb;
-	unsigned int n;
-
-	/* alloc skb which should be big enough for a whole multipart
-	 * message.  WARNING: has to be <= 128k due to slab restrictions */
-
-	n = max(inst_size, pkt_size);
-	skb = nfnetlink_alloc_skb(net, n, peer_portid, GFP_ATOMIC);
-	if (!skb) {
-		if (n > pkt_size) {
-			/* try to allocate only as much as we need for current
-			 * packet */
-
-			skb = nfnetlink_alloc_skb(net, pkt_size,
-						  peer_portid, GFP_ATOMIC);
-		}
-	}
-
-	return skb;
-}
-
-static void
-__nfulnl_send(struct nfulnl_instance *inst)
-{
-	if (inst->qlen > 1) {
-		struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
-						 NLMSG_DONE,
-						 sizeof(struct nfgenmsg),
-						 0);
-		if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n",
-			      inst->skb->len, skb_tailroom(inst->skb))) {
-			kfree_skb(inst->skb);
-			goto out;
-		}
-	}
-	nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
-			  MSG_DONTWAIT);
-out:
-	inst->qlen = 0;
-	inst->skb = NULL;
-}
-
-static void
-__nfulnl_flush(struct nfulnl_instance *inst)
-{
-	/* timer holds a reference */
-	if (del_timer(&inst->timer))
-		instance_put(inst);
-	if (inst->skb)
-		__nfulnl_send(inst);
-}
-
-static void
-nfulnl_timer(unsigned long data)
-{
-	struct nfulnl_instance *inst = (struct nfulnl_instance *)data;
-
-	spin_lock_bh(&inst->lock);
-	if (inst->skb)
-		__nfulnl_send(inst);
-	spin_unlock_bh(&inst->lock);
-	instance_put(inst);
-}
-
-/* This is an inline function, we don't really care about a long
- * list of arguments */
-static inline int
-__build_packet_message(struct nfnl_log_net *log,
-			struct nfulnl_instance *inst,
-			const struct sk_buff *skb,
-			unsigned int data_len,
-			u_int8_t pf,
-			unsigned int hooknum,
-			const struct net_device *indev,
-			const struct net_device *outdev,
-			const char *prefix, unsigned int plen)
-{
-	struct nfulnl_msg_packet_hdr pmsg;
-	struct nlmsghdr *nlh;
-	struct nfgenmsg *nfmsg;
-	sk_buff_data_t old_tail = inst->skb->tail;
-	struct sock *sk;
-	const unsigned char *hwhdrp;
-
-	nlh = nlmsg_put(inst->skb, 0, 0,
-			NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET,
-			sizeof(struct nfgenmsg), 0);
-	if (!nlh)
-		return -1;
-	nfmsg = nlmsg_data(nlh);
-	nfmsg->nfgen_family = pf;
-	nfmsg->version = NFNETLINK_V0;
-	nfmsg->res_id = htons(inst->group_num);
-
-	memset(&pmsg, 0, sizeof(pmsg));
-	pmsg.hw_protocol	= skb->protocol;
-	pmsg.hook		= hooknum;
-
-	if (nla_put(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg))
-		goto nla_put_failure;
-
-	if (prefix &&
-	    nla_put(inst->skb, NFULA_PREFIX, plen, prefix))
-		goto nla_put_failure;
-
-	if (indev) {
-#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-		if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
-				 htonl(indev->ifindex)))
-			goto nla_put_failure;
-#else
-		if (pf == PF_BRIDGE) {
-			/* Case 1: outdev is physical input device, we need to
-			 * look for bridge group (when called from
-			 * netfilter_bridge) */
-			if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
-					 htonl(indev->ifindex)) ||
-			/* this is the bridge group "brX" */
-			/* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
-			    nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
-					 htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
-				goto nla_put_failure;
-		} else {
-			struct net_device *physindev;
-
-			/* Case 2: indev is bridge group, we need to look for
-			 * physical device (when called from ipv4) */
-			if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
-					 htonl(indev->ifindex)))
-				goto nla_put_failure;
-
-			physindev = nf_bridge_get_physindev(skb);
-			if (physindev &&
-			    nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
-					 htonl(physindev->ifindex)))
-				goto nla_put_failure;
-		}
-#endif
-	}
-
-	if (outdev) {
-#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-		if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
-				 htonl(outdev->ifindex)))
-			goto nla_put_failure;
-#else
-		if (pf == PF_BRIDGE) {
-			/* Case 1: outdev is physical output device, we need to
-			 * look for bridge group (when called from
-			 * netfilter_bridge) */
-			if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
-					 htonl(outdev->ifindex)) ||
-			/* this is the bridge group "brX" */
-			/* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
-			    nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
-					 htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
-				goto nla_put_failure;
-		} else {
-			struct net_device *physoutdev;
-
-			/* Case 2: indev is a bridge group, we need to look
-			 * for physical device (when called from ipv4) */
-			if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
-					 htonl(outdev->ifindex)))
-				goto nla_put_failure;
-
-			physoutdev = nf_bridge_get_physoutdev(skb);
-			if (physoutdev &&
-			    nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
-					 htonl(physoutdev->ifindex)))
-				goto nla_put_failure;
-		}
-#endif
-	}
-
-	if (skb->mark &&
-	    nla_put_be32(inst->skb, NFULA_MARK, htonl(skb->mark)))
-		goto nla_put_failure;
-
-	if (indev && skb->dev &&
-	    skb->mac_header != skb->network_header) {
-		struct nfulnl_msg_packet_hw phw;
-		int len;
-
-		memset(&phw, 0, sizeof(phw));
-		len = dev_parse_header(skb, phw.hw_addr);
-		if (len > 0) {
-			phw.hw_addrlen = htons(len);
-			if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw))
-				goto nla_put_failure;
-		}
-	}
-
-	if (indev && skb_mac_header_was_set(skb)) {
-		if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) ||
-		    nla_put_be16(inst->skb, NFULA_HWLEN,
-				 htons(skb->dev->hard_header_len)))
-			goto nla_put_failure;
-
-		hwhdrp = skb_mac_header(skb);
-
-		if (skb->dev->type == ARPHRD_SIT)
-			hwhdrp -= ETH_HLEN;
-
-		if (hwhdrp >= skb->head &&
-		    nla_put(inst->skb, NFULA_HWHEADER,
-			    skb->dev->hard_header_len, hwhdrp))
-			goto nla_put_failure;
-	}
-
-	if (skb->tstamp.tv64) {
-		struct nfulnl_msg_packet_timestamp ts;
-		struct timeval tv = ktime_to_timeval(skb->tstamp);
-		ts.sec = cpu_to_be64(tv.tv_sec);
-		ts.usec = cpu_to_be64(tv.tv_usec);
-
-		if (nla_put(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts))
-			goto nla_put_failure;
-	}
-
-	/* UID */
-	sk = skb->sk;
-	if (sk && sk_fullsock(sk)) {
-		read_lock_bh(&sk->sk_callback_lock);
-		if (sk->sk_socket && sk->sk_socket->file) {
-			struct file *file = sk->sk_socket->file;
-			const struct cred *cred = file->f_cred;
-			struct user_namespace *user_ns = inst->peer_user_ns;
-			__be32 uid = htonl(from_kuid_munged(user_ns, cred->fsuid));
-			__be32 gid = htonl(from_kgid_munged(user_ns, cred->fsgid));
-			read_unlock_bh(&sk->sk_callback_lock);
-			if (nla_put_be32(inst->skb, NFULA_UID, uid) ||
-			    nla_put_be32(inst->skb, NFULA_GID, gid))
-				goto nla_put_failure;
-		} else
-			read_unlock_bh(&sk->sk_callback_lock);
-	}
-
-	/* local sequence number */
-	if ((inst->flags & NFULNL_CFG_F_SEQ) &&
-	    nla_put_be32(inst->skb, NFULA_SEQ, htonl(inst->seq++)))
-		goto nla_put_failure;
-
-	/* global sequence number */
-	if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) &&
-	    nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL,
-			 htonl(atomic_inc_return(&log->global_seq))))
-		goto nla_put_failure;
-
-	if (data_len) {
-		struct nlattr *nla;
-		int size = nla_attr_size(data_len);
-
-		if (skb_tailroom(inst->skb) < nla_total_size(data_len))
-			goto nla_put_failure;
-
-		nla = (struct nlattr *)skb_put(inst->skb, nla_total_size(data_len));
-		nla->nla_type = NFULA_PAYLOAD;
-		nla->nla_len = size;
-
-		if (skb_copy_bits(skb, 0, nla_data(nla), data_len))
-			BUG();
-	}
-
-	nlh->nlmsg_len = inst->skb->tail - old_tail;
-	return 0;
-
-nla_put_failure:
-	PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n");
-	return -1;
-}
-
-static struct nf_loginfo default_loginfo = {
-	.type =		NF_LOG_TYPE_ULOG,
-	.u = {
-		.ulog = {
-			.copy_len	= 0xffff,
-			.group		= 0,
-			.qthreshold	= 1,
-		},
-	},
-};
-
-/* log handler for internal netfilter logging api */
-void
-nfulnl_log_packet(struct net *net,
-		  u_int8_t pf,
-		  unsigned int hooknum,
-		  const struct sk_buff *skb,
-		  const struct net_device *in,
-		  const struct net_device *out,
-		  const struct nf_loginfo *li_user,
-		  const char *prefix)
-{
-	unsigned int size, data_len;
-	struct nfulnl_instance *inst;
-	const struct nf_loginfo *li;
-	unsigned int qthreshold;
-	unsigned int plen;
-	struct nfnl_log_net *log = nfnl_log_pernet(net);
-
-	if (li_user && li_user->type == NF_LOG_TYPE_ULOG)
-		li = li_user;
-	else
-		li = &default_loginfo;
-
-	inst = instance_lookup_get(log, li->u.ulog.group);
-	if (!inst)
-		return;
-
-	plen = 0;
-	if (prefix)
-		plen = strlen(prefix) + 1;
-
-	/* FIXME: do we want to make the size calculation conditional based on
-	 * what is actually present?  way more branches and checks, but more
-	 * memory efficient... */
-	size =    nlmsg_total_size(sizeof(struct nfgenmsg))
-		+ nla_total_size(sizeof(struct nfulnl_msg_packet_hdr))
-		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
-		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
-		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
-#endif
-		+ nla_total_size(sizeof(u_int32_t))	/* mark */
-		+ nla_total_size(sizeof(u_int32_t))	/* uid */
-		+ nla_total_size(sizeof(u_int32_t))	/* gid */
-		+ nla_total_size(plen)			/* prefix */
-		+ nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
-		+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp))
-		+ nla_total_size(sizeof(struct nfgenmsg));	/* NLMSG_DONE */
-
-	if (in && skb_mac_header_was_set(skb)) {
-		size +=   nla_total_size(skb->dev->hard_header_len)
-			+ nla_total_size(sizeof(u_int16_t))	/* hwtype */
-			+ nla_total_size(sizeof(u_int16_t));	/* hwlen */
-	}
-
-	spin_lock_bh(&inst->lock);
-
-	if (inst->flags & NFULNL_CFG_F_SEQ)
-		size += nla_total_size(sizeof(u_int32_t));
-	if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
-		size += nla_total_size(sizeof(u_int32_t));
-
-	qthreshold = inst->qthreshold;
-	/* per-rule qthreshold overrides per-instance */
-	if (li->u.ulog.qthreshold)
-		if (qthreshold > li->u.ulog.qthreshold)
-			qthreshold = li->u.ulog.qthreshold;
-
-
-	switch (inst->copy_mode) {
-	case NFULNL_COPY_META:
-	case NFULNL_COPY_NONE:
-		data_len = 0;
-		break;
-
-	case NFULNL_COPY_PACKET:
-		if (inst->copy_range > skb->len)
-			data_len = skb->len;
-		else
-			data_len = inst->copy_range;
-
-		size += nla_total_size(data_len);
-		break;
-
-	case NFULNL_COPY_DISABLED:
-	default:
-		goto unlock_and_release;
-	}
-
-	if (inst->skb && size > skb_tailroom(inst->skb)) {
-		/* either the queue len is too high or we don't have
-		 * enough room in the skb left. flush to userspace. */
-		__nfulnl_flush(inst);
-	}
-
-	if (!inst->skb) {
-		inst->skb = nfulnl_alloc_skb(net, inst->peer_portid,
-					     inst->nlbufsiz, size);
-		if (!inst->skb)
-			goto alloc_failure;
-	}
-
-	inst->qlen++;
-
-	__build_packet_message(log, inst, skb, data_len, pf,
-				hooknum, in, out, prefix, plen);
-
-	if (inst->qlen >= qthreshold)
-		__nfulnl_flush(inst);
-	/* timer_pending always called within inst->lock, so there
-	 * is no chance of a race here */
-	else if (!timer_pending(&inst->timer)) {
-		instance_get(inst);
-		inst->timer.expires = jiffies + (inst->flushtimeout*HZ/100);
-		add_timer(&inst->timer);
-	}
-
-unlock_and_release:
-	spin_unlock_bh(&inst->lock);
-	instance_put(inst);
-	return;
-
-alloc_failure:
-	/* FIXME: statistics */
-	goto unlock_and_release;
-}
-EXPORT_SYMBOL_GPL(nfulnl_log_packet);
-
-static int
-nfulnl_rcv_nl_event(struct notifier_block *this,
-		   unsigned long event, void *ptr)
-{
-	struct netlink_notify *n = ptr;
-	struct nfnl_log_net *log = nfnl_log_pernet(n->net);
-
-	if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) {
-		int i;
-
-		/* destroy all instances for this portid */
-		spin_lock_bh(&log->instances_lock);
-		for  (i = 0; i < INSTANCE_BUCKETS; i++) {
-			struct hlist_node *t2;
-			struct nfulnl_instance *inst;
-			struct hlist_head *head = &log->instance_table[i];
-
-			hlist_for_each_entry_safe(inst, t2, head, hlist) {
-				if (n->portid == inst->peer_portid)
-					__instance_destroy(inst);
-			}
-		}
-		spin_unlock_bh(&log->instances_lock);
-	}
-	return NOTIFY_DONE;
-}
-
-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[])
-{
-	return -ENOTSUPP;
-}
-
-static struct nf_logger nfulnl_logger __read_mostly = {
-	.name	= "nfnetlink_log",
-	.type	= NF_LOG_TYPE_ULOG,
-	.logfn	= &nfulnl_log_packet,
-	.me	= THIS_MODULE,
-};
-
-static const struct nla_policy nfula_cfg_policy[NFULA_CFG_MAX+1] = {
-	[NFULA_CFG_CMD]		= { .len = sizeof(struct nfulnl_msg_config_cmd) },
-	[NFULA_CFG_MODE]	= { .len = sizeof(struct nfulnl_msg_config_mode) },
-	[NFULA_CFG_TIMEOUT]	= { .type = NLA_U32 },
-	[NFULA_CFG_QTHRESH]	= { .type = NLA_U32 },
-	[NFULA_CFG_NLBUFSIZ]	= { .type = NLA_U32 },
-	[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[])
-{
-	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;
-
-	if (nfula[NFULA_CFG_CMD]) {
-		u_int8_t pf = nfmsg->nfgen_family;
-		cmd = nla_data(nfula[NFULA_CFG_CMD]);
-
-		/* Commands without queue context */
-		switch (cmd->command) {
-		case NFULNL_CFG_CMD_PF_BIND:
-			return nf_log_bind_pf(net, pf, &nfulnl_logger);
-		case NFULNL_CFG_CMD_PF_UNBIND:
-			nf_log_unbind_pf(net, pf);
-			return 0;
-		}
-	}
-
-	inst = instance_lookup_get(log, group_num);
-	if (inst && inst->peer_portid != NETLINK_CB(skb).portid) {
-		ret = -EPERM;
-		goto out_put;
-	}
-
-	if (cmd != NULL) {
-		switch (cmd->command) {
-		case NFULNL_CFG_CMD_BIND:
-			if (inst) {
-				ret = -EBUSY;
-				goto out_put;
-			}
-
-			inst = instance_create(net, group_num,
-					       NETLINK_CB(skb).portid,
-					       sk_user_ns(NETLINK_CB(skb).sk));
-			if (IS_ERR(inst)) {
-				ret = PTR_ERR(inst);
-				goto out;
-			}
-			break;
-		case NFULNL_CFG_CMD_UNBIND:
-			if (!inst) {
-				ret = -ENODEV;
-				goto out;
-			}
-
-			instance_destroy(log, inst);
-			goto out_put;
-		default:
-			ret = -ENOTSUPP;
-			break;
-		}
-	}
-
-	if (nfula[NFULA_CFG_MODE]) {
-		struct nfulnl_msg_config_mode *params;
-		params = nla_data(nfula[NFULA_CFG_MODE]);
-
-		if (!inst) {
-			ret = -ENODEV;
-			goto out;
-		}
-		nfulnl_set_mode(inst, params->copy_mode,
-				ntohl(params->copy_range));
-	}
-
-	if (nfula[NFULA_CFG_TIMEOUT]) {
-		__be32 timeout = nla_get_be32(nfula[NFULA_CFG_TIMEOUT]);
-
-		if (!inst) {
-			ret = -ENODEV;
-			goto out;
-		}
-		nfulnl_set_timeout(inst, ntohl(timeout));
-	}
-
-	if (nfula[NFULA_CFG_NLBUFSIZ]) {
-		__be32 nlbufsiz = nla_get_be32(nfula[NFULA_CFG_NLBUFSIZ]);
-
-		if (!inst) {
-			ret = -ENODEV;
-			goto out;
-		}
-		nfulnl_set_nlbufsiz(inst, ntohl(nlbufsiz));
-	}
-
-	if (nfula[NFULA_CFG_QTHRESH]) {
-		__be32 qthresh = nla_get_be32(nfula[NFULA_CFG_QTHRESH]);
-
-		if (!inst) {
-			ret = -ENODEV;
-			goto out;
-		}
-		nfulnl_set_qthresh(inst, ntohl(qthresh));
-	}
-
-	if (nfula[NFULA_CFG_FLAGS]) {
-		__be16 flags = nla_get_be16(nfula[NFULA_CFG_FLAGS]);
-
-		if (!inst) {
-			ret = -ENODEV;
-			goto out;
-		}
-		nfulnl_set_flags(inst, ntohs(flags));
-	}
-
-out_put:
-	instance_put(inst);
-out:
-	return ret;
-}
-
-static const struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = {
-	[NFULNL_MSG_PACKET]	= { .call = nfulnl_recv_unsupp,
-				    .attr_count = NFULA_MAX, },
-	[NFULNL_MSG_CONFIG]	= { .call = nfulnl_recv_config,
-				    .attr_count = NFULA_CFG_MAX,
-				    .policy = nfula_cfg_policy },
-};
-
-static const struct nfnetlink_subsystem nfulnl_subsys = {
-	.name		= "log",
-	.subsys_id	= NFNL_SUBSYS_ULOG,
-	.cb_count	= NFULNL_MSG_MAX,
-	.cb		= nfulnl_cb,
-};
-
-#ifdef CONFIG_PROC_FS
-struct iter_state {
-	struct seq_net_private p;
-	unsigned int bucket;
-};
-
-static struct hlist_node *get_first(struct net *net, struct iter_state *st)
-{
-	struct nfnl_log_net *log;
-	if (!st)
-		return NULL;
-
-	log = nfnl_log_pernet(net);
-
-	for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
-		struct hlist_head *head = &log->instance_table[st->bucket];
-
-		if (!hlist_empty(head))
-			return rcu_dereference_bh(hlist_first_rcu(head));
-	}
-	return NULL;
-}
-
-static struct hlist_node *get_next(struct net *net, struct iter_state *st,
-				   struct hlist_node *h)
-{
-	h = rcu_dereference_bh(hlist_next_rcu(h));
-	while (!h) {
-		struct nfnl_log_net *log;
-		struct hlist_head *head;
-
-		if (++st->bucket >= INSTANCE_BUCKETS)
-			return NULL;
-
-		log = nfnl_log_pernet(net);
-		head = &log->instance_table[st->bucket];
-		h = rcu_dereference_bh(hlist_first_rcu(head));
-	}
-	return h;
-}
-
-static struct hlist_node *get_idx(struct net *net, struct iter_state *st,
-				  loff_t pos)
-{
-	struct hlist_node *head;
-	head = get_first(net, st);
-
-	if (head)
-		while (pos && (head = get_next(net, st, head)))
-			pos--;
-	return pos ? NULL : head;
-}
-
-static void *seq_start(struct seq_file *s, loff_t *pos)
-	__acquires(rcu_bh)
-{
-	rcu_read_lock_bh();
-	return get_idx(seq_file_net(s), s->private, *pos);
-}
-
-static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
-	(*pos)++;
-	return get_next(seq_file_net(s), s->private, v);
-}
-
-static void seq_stop(struct seq_file *s, void *v)
-	__releases(rcu_bh)
-{
-	rcu_read_unlock_bh();
-}
-
-static int seq_show(struct seq_file *s, void *v)
-{
-	const struct nfulnl_instance *inst = v;
-
-	seq_printf(s, "%5u %6u %5u %1u %5u %6u %2u\n",
-		   inst->group_num,
-		   inst->peer_portid, inst->qlen,
-		   inst->copy_mode, inst->copy_range,
-		   inst->flushtimeout, atomic_read(&inst->use));
-
-	return 0;
-}
-
-static const struct seq_operations nful_seq_ops = {
-	.start	= seq_start,
-	.next	= seq_next,
-	.stop	= seq_stop,
-	.show	= seq_show,
-};
-
-static int nful_open(struct inode *inode, struct file *file)
-{
-	return seq_open_net(inode, file, &nful_seq_ops,
-			    sizeof(struct iter_state));
-}
-
-static const struct file_operations nful_file_ops = {
-	.owner	 = THIS_MODULE,
-	.open	 = nful_open,
-	.read	 = seq_read,
-	.llseek	 = seq_lseek,
-	.release = seq_release_net,
-};
-
-#endif /* PROC_FS */
-
-static int __net_init nfnl_log_net_init(struct net *net)
-{
-	unsigned int i;
-	struct nfnl_log_net *log = nfnl_log_pernet(net);
-
-	for (i = 0; i < INSTANCE_BUCKETS; i++)
-		INIT_HLIST_HEAD(&log->instance_table[i]);
-	spin_lock_init(&log->instances_lock);
-
-#ifdef CONFIG_PROC_FS
-	if (!proc_create("nfnetlink_log", 0440,
-			 net->nf.proc_netfilter, &nful_file_ops))
-		return -ENOMEM;
-#endif
-	return 0;
-}
-
-static void __net_exit nfnl_log_net_exit(struct net *net)
-{
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
-#endif
-	nf_log_unset(net, &nfulnl_logger);
-}
-
-static struct pernet_operations nfnl_log_net_ops = {
-	.init	= nfnl_log_net_init,
-	.exit	= nfnl_log_net_exit,
-	.id	= &nfnl_log_net_id,
-	.size	= sizeof(struct nfnl_log_net),
-};
-
-static int __init nfnetlink_log_init(void)
-{
-	int status;
-
-	status = register_pernet_subsys(&nfnl_log_net_ops);
-	if (status < 0) {
-		pr_err("failed to register pernet ops\n");
-		goto out;
-	}
-
-	netlink_register_notifier(&nfulnl_rtnl_notifier);
-	status = nfnetlink_subsys_register(&nfulnl_subsys);
-	if (status < 0) {
-		pr_err("failed to create netlink socket\n");
-		goto cleanup_netlink_notifier;
-	}
-
-	status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger);
-	if (status < 0) {
-		pr_err("failed to register logger\n");
-		goto cleanup_subsys;
-	}
-
-	return status;
-
-cleanup_subsys:
-	nfnetlink_subsys_unregister(&nfulnl_subsys);
-cleanup_netlink_notifier:
-	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
-	unregister_pernet_subsys(&nfnl_log_net_ops);
-out:
-	return status;
-}
-
-static void __exit nfnetlink_log_fini(void)
-{
-	nf_log_unregister(&nfulnl_logger);
-	nfnetlink_subsys_unregister(&nfulnl_subsys);
-	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
-	unregister_pernet_subsys(&nfnl_log_net_ops);
-}
-
-MODULE_DESCRIPTION("netfilter userspace logging");
-MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG);
-MODULE_ALIAS_NF_LOGGER(AF_INET, 1);
-MODULE_ALIAS_NF_LOGGER(AF_INET6, 1);
-MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 1);
-
-module_init(nfnetlink_log_init);
-module_exit(nfnetlink_log_fini);
diff --git a/net/netfilter/nfnetlink_log_core.c b/net/netfilter/nfnetlink_log_core.c
new file mode 100644
index 0000000..265ab85
--- /dev/null
+++ b/net/netfilter/nfnetlink_log_core.c
@@ -0,0 +1,1135 @@
+/*
+ * This is a module which is used for logging packets to userspace via
+ * nfetlink.
+ *
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ * (C) 2006-2012 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on the old ipv4-only ipt_ULOG.c:
+ * (C) 2000-2004 by Harald Welte <laforge@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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/netdevice.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_bridge.h>
+#include <net/netlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/spinlock.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/security.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <net/sock.h>
+#include <net/netfilter/nf_log.h>
+#include <net/netns/generic.h>
+#include <net/netfilter/nfnetlink_log.h>
+#include <net/netfilter/nfnetlink_queue.h>
+
+#include <linux/atomic.h>
+
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+#include "../bridge/br_private.h"
+#endif
+
+#define NFULNL_NLBUFSIZ_DEFAULT	NLMSG_GOODSIZE
+#define NFULNL_TIMEOUT_DEFAULT 	100	/* every second */
+#define NFULNL_QTHRESH_DEFAULT 	100	/* 100 packets */
+/* max packet size is limited by 16-bit struct nfattr nfa_len field */
+#define NFULNL_COPY_RANGE_MAX	(0xFFFF - NLA_HDRLEN)
+
+#define PRINTR(x, args...)	do { if (net_ratelimit()) \
+				     printk(x, ## args); } while (0);
+
+struct nfulnl_instance {
+	struct hlist_node hlist;	/* global list of instances */
+	spinlock_t lock;
+	atomic_t use;			/* use count */
+
+	unsigned int qlen;		/* number of nlmsgs in skb */
+	struct sk_buff *skb;		/* pre-allocatd skb */
+	struct timer_list timer;
+	struct net *net;
+	struct user_namespace *peer_user_ns;	/* User namespace of the peer process */
+	u32 peer_portid;		/* PORTID of the peer process */
+
+	/* configurable parameters */
+	unsigned int flushtimeout;	/* timeout until queue flush */
+	unsigned int nlbufsiz;		/* netlink buffer allocation size */
+	unsigned int qthreshold;	/* threshold of the queue */
+	u_int32_t copy_range;
+	u_int32_t seq;			/* instance-local sequential counter */
+	u_int16_t group_num;		/* number of this queue */
+	u_int16_t flags;
+	u_int8_t copy_mode;
+	struct rcu_head rcu;
+};
+
+#define INSTANCE_BUCKETS	16
+
+static int nfnl_log_net_id __read_mostly;
+
+struct nfnl_log_net {
+	spinlock_t instances_lock;
+	struct hlist_head instance_table[INSTANCE_BUCKETS];
+	atomic_t global_seq;
+};
+
+static struct nfnl_log_net *nfnl_log_pernet(struct net *net)
+{
+	return net_generic(net, nfnl_log_net_id);
+}
+
+static inline u_int8_t instance_hashfn(u_int16_t group_num)
+{
+	return ((group_num & 0xff) % INSTANCE_BUCKETS);
+}
+
+static struct nfulnl_instance *
+__instance_lookup(struct nfnl_log_net *log, u_int16_t group_num)
+{
+	struct hlist_head *head;
+	struct nfulnl_instance *inst;
+
+	head = &log->instance_table[instance_hashfn(group_num)];
+	hlist_for_each_entry_rcu(inst, head, hlist) {
+		if (inst->group_num == group_num)
+			return inst;
+	}
+	return NULL;
+}
+
+static inline void
+instance_get(struct nfulnl_instance *inst)
+{
+	atomic_inc(&inst->use);
+}
+
+static struct nfulnl_instance *
+instance_lookup_get(struct nfnl_log_net *log, u_int16_t group_num)
+{
+	struct nfulnl_instance *inst;
+
+	rcu_read_lock_bh();
+	inst = __instance_lookup(log, group_num);
+	if (inst && !atomic_inc_not_zero(&inst->use))
+		inst = NULL;
+	rcu_read_unlock_bh();
+
+	return inst;
+}
+
+static void nfulnl_instance_free_rcu(struct rcu_head *head)
+{
+	struct nfulnl_instance *inst =
+		container_of(head, struct nfulnl_instance, rcu);
+
+	put_net(inst->net);
+	kfree(inst);
+	module_put(THIS_MODULE);
+}
+
+static void
+instance_put(struct nfulnl_instance *inst)
+{
+	if (inst && atomic_dec_and_test(&inst->use))
+		call_rcu_bh(&inst->rcu, nfulnl_instance_free_rcu);
+}
+
+static void nfulnl_timer(unsigned long data);
+
+static struct nfulnl_instance *
+instance_create(struct net *net, u_int16_t group_num,
+		u32 portid, struct user_namespace *user_ns)
+{
+	struct nfulnl_instance *inst;
+	struct nfnl_log_net *log = nfnl_log_pernet(net);
+	int err;
+
+	spin_lock_bh(&log->instances_lock);
+	if (__instance_lookup(log, group_num)) {
+		err = -EEXIST;
+		goto out_unlock;
+	}
+
+	inst = kzalloc(sizeof(*inst), GFP_ATOMIC);
+	if (!inst) {
+		err = -ENOMEM;
+		goto out_unlock;
+	}
+
+	if (!try_module_get(THIS_MODULE)) {
+		kfree(inst);
+		err = -EAGAIN;
+		goto out_unlock;
+	}
+
+	INIT_HLIST_NODE(&inst->hlist);
+	spin_lock_init(&inst->lock);
+	/* needs to be two, since we _put() after creation */
+	atomic_set(&inst->use, 2);
+
+	setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst);
+
+	inst->net = get_net(net);
+	inst->peer_user_ns = user_ns;
+	inst->peer_portid = portid;
+	inst->group_num = group_num;
+
+	inst->qthreshold 	= NFULNL_QTHRESH_DEFAULT;
+	inst->flushtimeout 	= NFULNL_TIMEOUT_DEFAULT;
+	inst->nlbufsiz 		= NFULNL_NLBUFSIZ_DEFAULT;
+	inst->copy_mode 	= NFULNL_COPY_PACKET;
+	inst->copy_range 	= NFULNL_COPY_RANGE_MAX;
+
+	hlist_add_head_rcu(&inst->hlist,
+		       &log->instance_table[instance_hashfn(group_num)]);
+
+
+	spin_unlock_bh(&log->instances_lock);
+
+	return inst;
+
+out_unlock:
+	spin_unlock_bh(&log->instances_lock);
+	return ERR_PTR(err);
+}
+
+static void __nfulnl_flush(struct nfulnl_instance *inst);
+
+/* called with BH disabled */
+static void
+__instance_destroy(struct nfulnl_instance *inst)
+{
+	/* first pull it out of the global list */
+	hlist_del_rcu(&inst->hlist);
+
+	/* then flush all pending packets from skb */
+
+	spin_lock(&inst->lock);
+
+	/* lockless readers wont be able to use us */
+	inst->copy_mode = NFULNL_COPY_DISABLED;
+
+	if (inst->skb)
+		__nfulnl_flush(inst);
+	spin_unlock(&inst->lock);
+
+	/* and finally put the refcount */
+	instance_put(inst);
+}
+
+static inline void
+instance_destroy(struct nfnl_log_net *log,
+		 struct nfulnl_instance *inst)
+{
+	spin_lock_bh(&log->instances_lock);
+	__instance_destroy(inst);
+	spin_unlock_bh(&log->instances_lock);
+}
+
+static int
+nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
+		  unsigned int range)
+{
+	int status = 0;
+
+	spin_lock_bh(&inst->lock);
+
+	switch (mode) {
+	case NFULNL_COPY_NONE:
+	case NFULNL_COPY_META:
+		inst->copy_mode = mode;
+		inst->copy_range = 0;
+		break;
+
+	case NFULNL_COPY_PACKET:
+		inst->copy_mode = mode;
+		if (range == 0)
+			range = NFULNL_COPY_RANGE_MAX;
+		inst->copy_range = min_t(unsigned int,
+					 range, NFULNL_COPY_RANGE_MAX);
+		break;
+
+	default:
+		status = -EINVAL;
+		break;
+	}
+
+	spin_unlock_bh(&inst->lock);
+
+	return status;
+}
+
+static int
+nfulnl_set_nlbufsiz(struct nfulnl_instance *inst, u_int32_t nlbufsiz)
+{
+	int status;
+
+	spin_lock_bh(&inst->lock);
+	if (nlbufsiz < NFULNL_NLBUFSIZ_DEFAULT)
+		status = -ERANGE;
+	else if (nlbufsiz > 131072)
+		status = -ERANGE;
+	else {
+		inst->nlbufsiz = nlbufsiz;
+		status = 0;
+	}
+	spin_unlock_bh(&inst->lock);
+
+	return status;
+}
+
+static int
+nfulnl_set_timeout(struct nfulnl_instance *inst, u_int32_t timeout)
+{
+	spin_lock_bh(&inst->lock);
+	inst->flushtimeout = timeout;
+	spin_unlock_bh(&inst->lock);
+
+	return 0;
+}
+
+static int
+nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh)
+{
+	spin_lock_bh(&inst->lock);
+	inst->qthreshold = qthresh;
+	spin_unlock_bh(&inst->lock);
+
+	return 0;
+}
+
+static int
+nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags)
+{
+	spin_lock_bh(&inst->lock);
+	inst->flags = flags;
+	spin_unlock_bh(&inst->lock);
+
+	return 0;
+}
+
+static struct sk_buff *
+nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
+		 unsigned int pkt_size)
+{
+	struct sk_buff *skb;
+	unsigned int n;
+
+	/* alloc skb which should be big enough for a whole multipart
+	 * message.  WARNING: has to be <= 128k due to slab restrictions */
+
+	n = max(inst_size, pkt_size);
+	skb = nfnetlink_alloc_skb(net, n, peer_portid, GFP_ATOMIC);
+	if (!skb) {
+		if (n > pkt_size) {
+			/* try to allocate only as much as we need for current
+			 * packet */
+
+			skb = nfnetlink_alloc_skb(net, pkt_size,
+						  peer_portid, GFP_ATOMIC);
+		}
+	}
+
+	return skb;
+}
+
+static void
+__nfulnl_send(struct nfulnl_instance *inst)
+{
+	if (inst->qlen > 1) {
+		struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
+						 NLMSG_DONE,
+						 sizeof(struct nfgenmsg),
+						 0);
+		if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n",
+			      inst->skb->len, skb_tailroom(inst->skb))) {
+			kfree_skb(inst->skb);
+			goto out;
+		}
+	}
+	nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
+			  MSG_DONTWAIT);
+out:
+	inst->qlen = 0;
+	inst->skb = NULL;
+}
+
+static void
+__nfulnl_flush(struct nfulnl_instance *inst)
+{
+	/* timer holds a reference */
+	if (del_timer(&inst->timer))
+		instance_put(inst);
+	if (inst->skb)
+		__nfulnl_send(inst);
+}
+
+static void
+nfulnl_timer(unsigned long data)
+{
+	struct nfulnl_instance *inst = (struct nfulnl_instance *)data;
+
+	spin_lock_bh(&inst->lock);
+	if (inst->skb)
+		__nfulnl_send(inst);
+	spin_unlock_bh(&inst->lock);
+	instance_put(inst);
+}
+
+/* This is an inline function, we don't really care about a long
+ * list of arguments */
+static inline int
+__build_packet_message(struct nfnl_log_net *log,
+			struct nfulnl_instance *inst,
+			const struct sk_buff *skb,
+			unsigned int data_len,
+			u_int8_t pf,
+			unsigned int hooknum,
+			const struct net_device *indev,
+			const struct net_device *outdev,
+			const char *prefix, unsigned int plen,
+			struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+	struct nfulnl_msg_packet_hdr pmsg;
+	struct nlmsghdr *nlh;
+	struct nfgenmsg *nfmsg;
+	sk_buff_data_t old_tail = inst->skb->tail;
+	struct sock *sk;
+	const unsigned char *hwhdrp;
+
+	nlh = nlmsg_put(inst->skb, 0, 0,
+			NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET,
+			sizeof(struct nfgenmsg), 0);
+	if (!nlh)
+		return -1;
+	nfmsg = nlmsg_data(nlh);
+	nfmsg->nfgen_family = pf;
+	nfmsg->version = NFNETLINK_V0;
+	nfmsg->res_id = htons(inst->group_num);
+
+	memset(&pmsg, 0, sizeof(pmsg));
+	pmsg.hw_protocol	= skb->protocol;
+	pmsg.hook		= hooknum;
+
+	if (nla_put(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg))
+		goto nla_put_failure;
+
+	if (prefix &&
+	    nla_put(inst->skb, NFULA_PREFIX, plen, prefix))
+		goto nla_put_failure;
+
+	if (indev) {
+#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+		if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
+				 htonl(indev->ifindex)))
+			goto nla_put_failure;
+#else
+		if (pf == PF_BRIDGE) {
+			/* Case 1: outdev is physical input device, we need to
+			 * look for bridge group (when called from
+			 * netfilter_bridge) */
+			if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+					 htonl(indev->ifindex)) ||
+			/* this is the bridge group "brX" */
+			/* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
+			    nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
+					 htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
+				goto nla_put_failure;
+		} else {
+			struct net_device *physindev;
+
+			/* Case 2: indev is bridge group, we need to look for
+			 * physical device (when called from ipv4) */
+			if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
+					 htonl(indev->ifindex)))
+				goto nla_put_failure;
+
+			physindev = nf_bridge_get_physindev(skb);
+			if (physindev &&
+			    nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+					 htonl(physindev->ifindex)))
+				goto nla_put_failure;
+		}
+#endif
+	}
+
+	if (outdev) {
+#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+		if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
+				 htonl(outdev->ifindex)))
+			goto nla_put_failure;
+#else
+		if (pf == PF_BRIDGE) {
+			/* Case 1: outdev is physical output device, we need to
+			 * look for bridge group (when called from
+			 * netfilter_bridge) */
+			if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+					 htonl(outdev->ifindex)) ||
+			/* this is the bridge group "brX" */
+			/* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
+			    nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
+					 htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
+				goto nla_put_failure;
+		} else {
+			struct net_device *physoutdev;
+
+			/* Case 2: indev is a bridge group, we need to look
+			 * for physical device (when called from ipv4) */
+			if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
+					 htonl(outdev->ifindex)))
+				goto nla_put_failure;
+
+			physoutdev = nf_bridge_get_physoutdev(skb);
+			if (physoutdev &&
+			    nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+					 htonl(physoutdev->ifindex)))
+				goto nla_put_failure;
+		}
+#endif
+	}
+
+	if (skb->mark &&
+	    nla_put_be32(inst->skb, NFULA_MARK, htonl(skb->mark)))
+		goto nla_put_failure;
+
+	if (indev && skb->dev &&
+	    skb->mac_header != skb->network_header) {
+		struct nfulnl_msg_packet_hw phw;
+		int len;
+
+		memset(&phw, 0, sizeof(phw));
+		len = dev_parse_header(skb, phw.hw_addr);
+		if (len > 0) {
+			phw.hw_addrlen = htons(len);
+			if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw))
+				goto nla_put_failure;
+		}
+	}
+
+	if (indev && skb_mac_header_was_set(skb)) {
+		if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) ||
+		    nla_put_be16(inst->skb, NFULA_HWLEN,
+				 htons(skb->dev->hard_header_len)))
+			goto nla_put_failure;
+
+		hwhdrp = skb_mac_header(skb);
+
+		if (skb->dev->type == ARPHRD_SIT)
+			hwhdrp -= ETH_HLEN;
+
+		if (hwhdrp >= skb->head &&
+		    nla_put(inst->skb, NFULA_HWHEADER,
+			    skb->dev->hard_header_len, hwhdrp))
+			goto nla_put_failure;
+	}
+
+	if (skb->tstamp.tv64) {
+		struct nfulnl_msg_packet_timestamp ts;
+		struct timeval tv = ktime_to_timeval(skb->tstamp);
+		ts.sec = cpu_to_be64(tv.tv_sec);
+		ts.usec = cpu_to_be64(tv.tv_usec);
+
+		if (nla_put(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts))
+			goto nla_put_failure;
+	}
+
+	/* UID */
+	sk = skb->sk;
+	if (sk && sk_fullsock(sk)) {
+		read_lock_bh(&sk->sk_callback_lock);
+		if (sk->sk_socket && sk->sk_socket->file) {
+			struct file *file = sk->sk_socket->file;
+			const struct cred *cred = file->f_cred;
+			struct user_namespace *user_ns = inst->peer_user_ns;
+			__be32 uid = htonl(from_kuid_munged(user_ns, cred->fsuid));
+			__be32 gid = htonl(from_kgid_munged(user_ns, cred->fsgid));
+			read_unlock_bh(&sk->sk_callback_lock);
+			if (nla_put_be32(inst->skb, NFULA_UID, uid) ||
+			    nla_put_be32(inst->skb, NFULA_GID, gid))
+				goto nla_put_failure;
+		} else
+			read_unlock_bh(&sk->sk_callback_lock);
+	}
+
+	/* local sequence number */
+	if ((inst->flags & NFULNL_CFG_F_SEQ) &&
+	    nla_put_be32(inst->skb, NFULA_SEQ, htonl(inst->seq++)))
+		goto nla_put_failure;
+
+	/* global sequence number */
+	if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) &&
+	    nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL,
+			 htonl(atomic_inc_return(&log->global_seq))))
+		goto nla_put_failure;
+
+	/* conntrack */
+	if (ct && nfqnl_ct_put(inst->skb, ct, NFULA_CT,
+			       ctinfo, NFULA_CT_INFO) < 0)
+		goto nla_put_failure;
+
+	if (data_len) {
+		struct nlattr *nla;
+		int size = nla_attr_size(data_len);
+
+		if (skb_tailroom(inst->skb) < nla_total_size(data_len))
+			goto nla_put_failure;
+
+		nla = (struct nlattr *)skb_put(inst->skb, nla_total_size(data_len));
+		nla->nla_type = NFULA_PAYLOAD;
+		nla->nla_len = size;
+
+		if (skb_copy_bits(skb, 0, nla_data(nla), data_len))
+			BUG();
+	}
+
+	nlh->nlmsg_len = inst->skb->tail - old_tail;
+	return 0;
+
+nla_put_failure:
+	PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n");
+	return -1;
+}
+
+static struct nf_loginfo default_loginfo = {
+	.type =		NF_LOG_TYPE_ULOG,
+	.u = {
+		.ulog = {
+			.copy_len	= 0xffff,
+			.group		= 0,
+			.qthreshold	= 1,
+		},
+	},
+};
+
+/* log handler for internal netfilter logging api */
+void
+nfulnl_log_packet(struct net *net,
+		  u_int8_t pf,
+		  unsigned int hooknum,
+		  const struct sk_buff *skb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  const struct nf_loginfo *li_user,
+		  const char *prefix)
+{
+	size_t size;
+	unsigned int data_len;
+	struct nfulnl_instance *inst;
+	const struct nf_loginfo *li;
+	unsigned int qthreshold;
+	unsigned int plen;
+	struct nfnl_log_net *log = nfnl_log_pernet(net);
+	struct nf_conn *ct = NULL;
+	enum ip_conntrack_info uninitialized_var(ctinfo);
+
+	if (li_user && li_user->type == NF_LOG_TYPE_ULOG)
+		li = li_user;
+	else
+		li = &default_loginfo;
+
+	inst = instance_lookup_get(log, li->u.ulog.group);
+	if (!inst)
+		return;
+
+	plen = 0;
+	if (prefix)
+		plen = strlen(prefix) + 1;
+
+	/* FIXME: do we want to make the size calculation conditional based on
+	 * what is actually present?  way more branches and checks, but more
+	 * memory efficient... */
+	size =    nlmsg_total_size(sizeof(struct nfgenmsg))
+		+ nla_total_size(sizeof(struct nfulnl_msg_packet_hdr))
+		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
+		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
+		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
+#endif
+		+ nla_total_size(sizeof(u_int32_t))	/* mark */
+		+ nla_total_size(sizeof(u_int32_t))	/* uid */
+		+ nla_total_size(sizeof(u_int32_t))	/* gid */
+		+ nla_total_size(plen)			/* prefix */
+		+ nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
+		+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp))
+		+ nla_total_size(sizeof(struct nfgenmsg));	/* NLMSG_DONE */
+
+	if (in && skb_mac_header_was_set(skb)) {
+		size +=   nla_total_size(skb->dev->hard_header_len)
+			+ nla_total_size(sizeof(u_int16_t))	/* hwtype */
+			+ nla_total_size(sizeof(u_int16_t));	/* hwlen */
+	}
+
+	spin_lock_bh(&inst->lock);
+
+	if (inst->flags & NFULNL_CFG_F_SEQ)
+		size += nla_total_size(sizeof(u_int32_t));
+	if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
+		size += nla_total_size(sizeof(u_int32_t));
+	if (inst->flags & NFULNL_CFG_F_CONNTRACK)
+		ct = nfqnl_ct_get(skb, &size, &ctinfo);
+
+	qthreshold = inst->qthreshold;
+	/* per-rule qthreshold overrides per-instance */
+	if (li->u.ulog.qthreshold)
+		if (qthreshold > li->u.ulog.qthreshold)
+			qthreshold = li->u.ulog.qthreshold;
+
+
+	switch (inst->copy_mode) {
+	case NFULNL_COPY_META:
+	case NFULNL_COPY_NONE:
+		data_len = 0;
+		break;
+
+	case NFULNL_COPY_PACKET:
+		if (inst->copy_range > skb->len)
+			data_len = skb->len;
+		else
+			data_len = inst->copy_range;
+
+		size += nla_total_size(data_len);
+		break;
+
+	case NFULNL_COPY_DISABLED:
+	default:
+		goto unlock_and_release;
+	}
+
+	if (inst->skb && size > skb_tailroom(inst->skb)) {
+		/* either the queue len is too high or we don't have
+		 * enough room in the skb left. flush to userspace. */
+		__nfulnl_flush(inst);
+	}
+
+	if (!inst->skb) {
+		inst->skb = nfulnl_alloc_skb(net, inst->peer_portid,
+					     inst->nlbufsiz, size);
+		if (!inst->skb)
+			goto alloc_failure;
+	}
+
+	inst->qlen++;
+
+	__build_packet_message(log, inst, skb, data_len, pf,
+			       hooknum, in, out, prefix, plen, ct, ctinfo);
+
+	if (inst->qlen >= qthreshold)
+		__nfulnl_flush(inst);
+	/* timer_pending always called within inst->lock, so there
+	 * is no chance of a race here */
+	else if (!timer_pending(&inst->timer)) {
+		instance_get(inst);
+		inst->timer.expires = jiffies + (inst->flushtimeout*HZ/100);
+		add_timer(&inst->timer);
+	}
+
+unlock_and_release:
+	spin_unlock_bh(&inst->lock);
+	instance_put(inst);
+	return;
+
+alloc_failure:
+	/* FIXME: statistics */
+	goto unlock_and_release;
+}
+EXPORT_SYMBOL_GPL(nfulnl_log_packet);
+
+static int
+nfulnl_rcv_nl_event(struct notifier_block *this,
+		   unsigned long event, void *ptr)
+{
+	struct netlink_notify *n = ptr;
+	struct nfnl_log_net *log = nfnl_log_pernet(n->net);
+
+	if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) {
+		int i;
+
+		/* destroy all instances for this portid */
+		spin_lock_bh(&log->instances_lock);
+		for  (i = 0; i < INSTANCE_BUCKETS; i++) {
+			struct hlist_node *t2;
+			struct nfulnl_instance *inst;
+			struct hlist_head *head = &log->instance_table[i];
+
+			hlist_for_each_entry_safe(inst, t2, head, hlist) {
+				if (n->portid == inst->peer_portid)
+					__instance_destroy(inst);
+			}
+		}
+		spin_unlock_bh(&log->instances_lock);
+	}
+	return NOTIFY_DONE;
+}
+
+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[])
+{
+	return -ENOTSUPP;
+}
+
+static struct nf_logger nfulnl_logger __read_mostly = {
+	.name	= "nfnetlink_log",
+	.type	= NF_LOG_TYPE_ULOG,
+	.logfn	= &nfulnl_log_packet,
+	.me	= THIS_MODULE,
+};
+
+static const struct nla_policy nfula_cfg_policy[NFULA_CFG_MAX+1] = {
+	[NFULA_CFG_CMD]		= { .len = sizeof(struct nfulnl_msg_config_cmd) },
+	[NFULA_CFG_MODE]	= { .len = sizeof(struct nfulnl_msg_config_mode) },
+	[NFULA_CFG_TIMEOUT]	= { .type = NLA_U32 },
+	[NFULA_CFG_QTHRESH]	= { .type = NLA_U32 },
+	[NFULA_CFG_NLBUFSIZ]	= { .type = NLA_U32 },
+	[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[])
+{
+	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;
+
+	if (nfula[NFULA_CFG_CMD]) {
+		u_int8_t pf = nfmsg->nfgen_family;
+		cmd = nla_data(nfula[NFULA_CFG_CMD]);
+
+		/* Commands without queue context */
+		switch (cmd->command) {
+		case NFULNL_CFG_CMD_PF_BIND:
+			return nf_log_bind_pf(net, pf, &nfulnl_logger);
+		case NFULNL_CFG_CMD_PF_UNBIND:
+			nf_log_unbind_pf(net, pf);
+			return 0;
+		}
+	}
+
+	inst = instance_lookup_get(log, group_num);
+	if (inst && inst->peer_portid != NETLINK_CB(skb).portid) {
+		ret = -EPERM;
+		goto out_put;
+	}
+
+	if (cmd != NULL) {
+		switch (cmd->command) {
+		case NFULNL_CFG_CMD_BIND:
+			if (inst) {
+				ret = -EBUSY;
+				goto out_put;
+			}
+
+			inst = instance_create(net, group_num,
+					       NETLINK_CB(skb).portid,
+					       sk_user_ns(NETLINK_CB(skb).sk));
+			if (IS_ERR(inst)) {
+				ret = PTR_ERR(inst);
+				goto out;
+			}
+			break;
+		case NFULNL_CFG_CMD_UNBIND:
+			if (!inst) {
+				ret = -ENODEV;
+				goto out;
+			}
+
+			instance_destroy(log, inst);
+			goto out_put;
+		default:
+			ret = -ENOTSUPP;
+			break;
+		}
+	}
+
+	if (nfula[NFULA_CFG_MODE]) {
+		struct nfulnl_msg_config_mode *params;
+		params = nla_data(nfula[NFULA_CFG_MODE]);
+
+		if (!inst) {
+			ret = -ENODEV;
+			goto out;
+		}
+		nfulnl_set_mode(inst, params->copy_mode,
+				ntohl(params->copy_range));
+	}
+
+	if (nfula[NFULA_CFG_TIMEOUT]) {
+		__be32 timeout = nla_get_be32(nfula[NFULA_CFG_TIMEOUT]);
+
+		if (!inst) {
+			ret = -ENODEV;
+			goto out;
+		}
+		nfulnl_set_timeout(inst, ntohl(timeout));
+	}
+
+	if (nfula[NFULA_CFG_NLBUFSIZ]) {
+		__be32 nlbufsiz = nla_get_be32(nfula[NFULA_CFG_NLBUFSIZ]);
+
+		if (!inst) {
+			ret = -ENODEV;
+			goto out;
+		}
+		nfulnl_set_nlbufsiz(inst, ntohl(nlbufsiz));
+	}
+
+	if (nfula[NFULA_CFG_QTHRESH]) {
+		__be32 qthresh = nla_get_be32(nfula[NFULA_CFG_QTHRESH]);
+
+		if (!inst) {
+			ret = -ENODEV;
+			goto out;
+		}
+		nfulnl_set_qthresh(inst, ntohl(qthresh));
+	}
+
+	if (nfula[NFULA_CFG_FLAGS]) {
+		__be16 flags = nla_get_be16(nfula[NFULA_CFG_FLAGS]);
+
+		if (!inst) {
+			ret = -ENODEV;
+			goto out;
+		}
+		nfulnl_set_flags(inst, ntohs(flags));
+	}
+
+out_put:
+	instance_put(inst);
+out:
+	return ret;
+}
+
+static const struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = {
+	[NFULNL_MSG_PACKET]	= { .call = nfulnl_recv_unsupp,
+				    .attr_count = NFULA_MAX, },
+	[NFULNL_MSG_CONFIG]	= { .call = nfulnl_recv_config,
+				    .attr_count = NFULA_CFG_MAX,
+				    .policy = nfula_cfg_policy },
+};
+
+static const struct nfnetlink_subsystem nfulnl_subsys = {
+	.name		= "log",
+	.subsys_id	= NFNL_SUBSYS_ULOG,
+	.cb_count	= NFULNL_MSG_MAX,
+	.cb		= nfulnl_cb,
+};
+
+#ifdef CONFIG_PROC_FS
+struct iter_state {
+	struct seq_net_private p;
+	unsigned int bucket;
+};
+
+static struct hlist_node *get_first(struct net *net, struct iter_state *st)
+{
+	struct nfnl_log_net *log;
+	if (!st)
+		return NULL;
+
+	log = nfnl_log_pernet(net);
+
+	for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
+		struct hlist_head *head = &log->instance_table[st->bucket];
+
+		if (!hlist_empty(head))
+			return rcu_dereference_bh(hlist_first_rcu(head));
+	}
+	return NULL;
+}
+
+static struct hlist_node *get_next(struct net *net, struct iter_state *st,
+				   struct hlist_node *h)
+{
+	h = rcu_dereference_bh(hlist_next_rcu(h));
+	while (!h) {
+		struct nfnl_log_net *log;
+		struct hlist_head *head;
+
+		if (++st->bucket >= INSTANCE_BUCKETS)
+			return NULL;
+
+		log = nfnl_log_pernet(net);
+		head = &log->instance_table[st->bucket];
+		h = rcu_dereference_bh(hlist_first_rcu(head));
+	}
+	return h;
+}
+
+static struct hlist_node *get_idx(struct net *net, struct iter_state *st,
+				  loff_t pos)
+{
+	struct hlist_node *head;
+	head = get_first(net, st);
+
+	if (head)
+		while (pos && (head = get_next(net, st, head)))
+			pos--;
+	return pos ? NULL : head;
+}
+
+static void *seq_start(struct seq_file *s, loff_t *pos)
+	__acquires(rcu_bh)
+{
+	rcu_read_lock_bh();
+	return get_idx(seq_file_net(s), s->private, *pos);
+}
+
+static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return get_next(seq_file_net(s), s->private, v);
+}
+
+static void seq_stop(struct seq_file *s, void *v)
+	__releases(rcu_bh)
+{
+	rcu_read_unlock_bh();
+}
+
+static int seq_show(struct seq_file *s, void *v)
+{
+	const struct nfulnl_instance *inst = v;
+
+	seq_printf(s, "%5u %6u %5u %1u %5u %6u %2u\n",
+		   inst->group_num,
+		   inst->peer_portid, inst->qlen,
+		   inst->copy_mode, inst->copy_range,
+		   inst->flushtimeout, atomic_read(&inst->use));
+
+	return 0;
+}
+
+static const struct seq_operations nful_seq_ops = {
+	.start	= seq_start,
+	.next	= seq_next,
+	.stop	= seq_stop,
+	.show	= seq_show,
+};
+
+static int nful_open(struct inode *inode, struct file *file)
+{
+	return seq_open_net(inode, file, &nful_seq_ops,
+			    sizeof(struct iter_state));
+}
+
+static const struct file_operations nful_file_ops = {
+	.owner	 = THIS_MODULE,
+	.open	 = nful_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = seq_release_net,
+};
+
+#endif /* PROC_FS */
+
+static int __net_init nfnl_log_net_init(struct net *net)
+{
+	unsigned int i;
+	struct nfnl_log_net *log = nfnl_log_pernet(net);
+
+	for (i = 0; i < INSTANCE_BUCKETS; i++)
+		INIT_HLIST_HEAD(&log->instance_table[i]);
+	spin_lock_init(&log->instances_lock);
+
+#ifdef CONFIG_PROC_FS
+	if (!proc_create("nfnetlink_log", 0440,
+			 net->nf.proc_netfilter, &nful_file_ops))
+		return -ENOMEM;
+#endif
+	return 0;
+}
+
+static void __net_exit nfnl_log_net_exit(struct net *net)
+{
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
+#endif
+	nf_log_unset(net, &nfulnl_logger);
+}
+
+static struct pernet_operations nfnl_log_net_ops = {
+	.init	= nfnl_log_net_init,
+	.exit	= nfnl_log_net_exit,
+	.id	= &nfnl_log_net_id,
+	.size	= sizeof(struct nfnl_log_net),
+};
+
+static int __init nfnetlink_log_init(void)
+{
+	int status;
+
+	status = register_pernet_subsys(&nfnl_log_net_ops);
+	if (status < 0) {
+		pr_err("failed to register pernet ops\n");
+		goto out;
+	}
+
+	netlink_register_notifier(&nfulnl_rtnl_notifier);
+	status = nfnetlink_subsys_register(&nfulnl_subsys);
+	if (status < 0) {
+		pr_err("failed to create netlink socket\n");
+		goto cleanup_netlink_notifier;
+	}
+
+	status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger);
+	if (status < 0) {
+		pr_err("failed to register logger\n");
+		goto cleanup_subsys;
+	}
+
+	return status;
+
+cleanup_subsys:
+	nfnetlink_subsys_unregister(&nfulnl_subsys);
+cleanup_netlink_notifier:
+	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
+	unregister_pernet_subsys(&nfnl_log_net_ops);
+out:
+	return status;
+}
+
+static void __exit nfnetlink_log_fini(void)
+{
+	nf_log_unregister(&nfulnl_logger);
+	nfnetlink_subsys_unregister(&nfulnl_subsys);
+	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
+	unregister_pernet_subsys(&nfnl_log_net_ops);
+}
+
+MODULE_DESCRIPTION("netfilter userspace logging");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG);
+MODULE_ALIAS_NF_LOGGER(AF_INET, 1);
+MODULE_ALIAS_NF_LOGGER(AF_INET6, 1);
+MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 1);
+
+module_init(nfnetlink_log_init);
+module_exit(nfnetlink_log_fini);
diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c
index 2a30618..d7908c5 100644
--- a/net/netfilter/nfnetlink_queue_ct.c
+++ b/net/netfilter/nfnetlink_queue_ct.c
@@ -14,7 +14,7 @@
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nfnetlink_queue.h>
 
-struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
+struct nf_conn *nfqnl_ct_get(const struct sk_buff *entskb, size_t *size,
 			     enum ip_conntrack_info *ctinfo)
 {
 	struct nfq_ct_hook *nfq_ct;
-- 
1.7.10.4

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

* Re: [PATCH nf-next 2/2] netfilter: nfnetlink_log: allow to attach conntrack
  2015-08-24 23:15 ` [PATCH nf-next 2/2] netfilter: nfnetlink_log: allow to attach conntrack Ken-ichirou MATSUZAWA
@ 2015-08-26 19:05   ` Pablo Neira Ayuso
  2015-08-28  6:43     ` Ken-ichirou MATSUZAWA
  2015-09-01  0:34     ` Ken-ichirou MATSUZAWA
  0 siblings, 2 replies; 13+ messages in thread
From: Pablo Neira Ayuso @ 2015-08-26 19:05 UTC (permalink / raw)
  To: Ken-ichirou MATSUZAWA; +Cc: The netfilter developer mailinglist

On Tue, Aug 25, 2015 at 08:15:20AM +0900, Ken-ichirou MATSUZAWA wrote:
> This patch enables to include the conntrack information together
> with the packet that is sent to user-space via NFLOG, then a
> user-space program can acquire NATed information by this NFULA_CT
> attribute.
> 
> Including the conntrack information is optional, you can set it
> via NFULNL_CFG_F_CONNTRACK flag with the NFULA_CFG_FLAGS attribute
> like NFQUEUE.

No objections to this series, just several comments below on them.

> Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
> ---
>  include/net/netfilter/nfnetlink_queue.h      |    4 +-
>  include/uapi/linux/netfilter/nfnetlink_log.h |    3 +
>  net/netfilter/Kconfig                        |    9 +-
>  net/netfilter/Makefile                       |    2 +
>  net/netfilter/nfnetlink_log.c                | 1123 -------------------------
>  net/netfilter/nfnetlink_log_core.c           | 1135 ++++++++++++++++++++++++++
>  net/netfilter/nfnetlink_queue_ct.c           |    2 +-
>  7 files changed, 1148 insertions(+), 1130 deletions(-)
>  delete mode 100644 net/netfilter/nfnetlink_log.c
>  create mode 100644 net/netfilter/nfnetlink_log_core.c
> 
> diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h
> index f94942b..05315ab 100644
> --- a/include/net/netfilter/nfnetlink_queue.h
> +++ b/include/net/netfilter/nfnetlink_queue.h
> @@ -6,7 +6,7 @@
>  struct nf_conn;
>  
>  #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
> -struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
> +struct nf_conn *nfqnl_ct_get(const struct sk_buff *entskb, size_t *size,
>  			     enum ip_conntrack_info *ctinfo);
>  struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
>  			       const struct nlattr *attr,
> @@ -20,7 +20,7 @@ int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
>  			u32 portid, u32 report);
>  #else
>  inline struct nf_conn *
> -nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
> +nfqnl_ct_get(const struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
>  {
>  	return NULL;
>  }
> diff --git a/include/uapi/linux/netfilter/nfnetlink_log.h b/include/uapi/linux/netfilter/nfnetlink_log.h
> index 90c2c95..081e7f9 100644
> --- a/include/uapi/linux/netfilter/nfnetlink_log.h
> +++ b/include/uapi/linux/netfilter/nfnetlink_log.h
> @@ -51,6 +51,8 @@ enum nfulnl_attr_type {
>  	NFULA_HWTYPE,			/* hardware type */
>  	NFULA_HWHEADER,			/* hardware header */
>  	NFULA_HWLEN,			/* hardware header length */
> +	NFULA_CT,			/* nf_conntrack_netlink.h */
> +	NFULA_CT_INFO,			/* enum ip_conntrack_info */
>  
>  	__NFULA_MAX
>  };
> @@ -93,5 +95,6 @@ enum nfulnl_attr_config {
>  
>  #define NFULNL_CFG_F_SEQ	0x0001
>  #define NFULNL_CFG_F_SEQ_GLOBAL	0x0002
> +#define NFULNL_CFG_F_CONNTRACK	0x0004
>  
>  #endif /* _NFNETLINK_LOG_H */
> diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
> index 3e1b4ab..b3db079 100644
> --- a/net/netfilter/Kconfig
> +++ b/net/netfilter/Kconfig
> @@ -363,12 +363,13 @@ config NF_CT_NETLINK_HELPER
>  	  If unsure, say `N'.
>  
>  config NETFILTER_NETLINK_QUEUE_CT
> -        bool "NFQUEUE integration with Connection Tracking"
> +        bool "NFQUEUE/NFLOG integration with Connection Tracking"
>          default n
> -        depends on NETFILTER_NETLINK_QUEUE
> +        depends on NETFILTER_NETLINK_QUEUE || NETFILTER_NETLINK_LOG
>  	help
> -	  If this option is enabled, NFQUEUE can include Connection Tracking
> -	  information together with the packet is the enqueued via NFNETLINK.
> +	  If this option is enabled, NFQUEUE and/or NFLOG can include
> +	  Connection Tracking information together with the packet is
> +	  enqueued, logged via NFNETLINK.

You better add another Kconfig for _LOG.

>  config NF_NAT
>  	tristate
> diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
> index 70d026d..3657898 100644
> --- a/net/netfilter/Makefile
> +++ b/net/netfilter/Makefile
> @@ -13,6 +13,8 @@ obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o
>  nfnetlink_queue-y := nfnetlink_queue_core.o
>  nfnetlink_queue-$(CONFIG_NETFILTER_NETLINK_QUEUE_CT) += nfnetlink_queue_ct.o
>  obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
> +nfnetlink_log-y := nfnetlink_log_core.o
> +nfnetlink_log-$(CONFIG_NETFILTER_NETLINK_QUEUE_CT) += nfnetlink_queue_ct.o
>  obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
>  
>  # connection tracking
> diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
> deleted file mode 100644
> index 4670821..0000000
> --- a/net/netfilter/nfnetlink_log.c
> +++ /dev/null

Could you use -M option when generating patches?

       -M[<n>], --find-renames[=<n>]
           Detect renames. If n is specified, it is a
           threshold on the similarity index (i.e.
           amount of addition/deletions compared to
           the file’s size). For example, -M90% means
           git should consider a delete/add pair to be
           a rename if more than 90% of the file
           hasn’t changed.

It would be good if your first patch renamed the file, then you make
the changes in a follow up patch.

The idea is to make it easier for people to review your changes.

Thanks.
--
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] 13+ messages in thread

* Re: [PATCH nf-next 2/2] netfilter: nfnetlink_log: allow to attach conntrack
  2015-08-26 19:05   ` Pablo Neira Ayuso
@ 2015-08-28  6:43     ` Ken-ichirou MATSUZAWA
  2015-09-01  0:34     ` Ken-ichirou MATSUZAWA
  1 sibling, 0 replies; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-08-28  6:43 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

On Wed, Aug 26, 2015 at 09:05:53PM +0200, Pablo Neira Ayuso wrote:
> On Tue, Aug 25, 2015 at 08:15:20AM +0900, Ken-ichirou MATSUZAWA wrote:
> > This patch enables to include the conntrack information together
> > with the packet that is sent to user-space via NFLOG, then a
> > user-space program can acquire NATed information by this NFULA_CT
> > attribute.
> > 
> No objections to this series, just several comments below on them.

Thank you for your taking time. But I realize these can not be
statically built into kernel, sorry.

> >  config NETFILTER_NETLINK_QUEUE_CT
> > -        bool "NFQUEUE integration with Connection Tracking"
> > +        bool "NFQUEUE/NFLOG integration with Connection Tracking"
> >          default n
> > -        depends on NETFILTER_NETLINK_QUEUE
> > +        depends on NETFILTER_NETLINK_QUEUE || NETFILTER_NETLINK_LOG
> >  	help
> > -	  If this option is enabled, NFQUEUE can include Connection Tracking
> > -	  information together with the packet is the enqueued via NFNETLINK.
> > +	  If this option is enabled, NFQUEUE and/or NFLOG can include
> > +	  Connection Tracking information together with the packet is
> > +	  enqueued, logged via NFNETLINK.
> 
> You better add another Kconfig for _LOG.

I'll follow your instruction, thanks.
I have to reconsider to enable it statically linked and will be glad
if you review again at the next time.

Thanks,

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

* Re: [PATCH nf-next 2/2] netfilter: nfnetlink_log: allow to attach conntrack
  2015-08-26 19:05   ` Pablo Neira Ayuso
  2015-08-28  6:43     ` Ken-ichirou MATSUZAWA
@ 2015-09-01  0:34     ` Ken-ichirou MATSUZAWA
  2015-09-01  0:37       ` [PATCHv2 nf-next 1/5] netfilter: nfnetlink_queue: enable to specify nla type Ken-ichirou MATSUZAWA
                         ` (4 more replies)
  1 sibling, 5 replies; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-09-01  0:34 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

The compile fails if both nflog and nfqueue are built-in at the
previous patch.

I am trying to link nf_netlink_queue_ct to nf_conntrack_netlink, not
to nf_netlink_queue_core, to avoid the compilation fail in the
following patch series. The idea is that nfqueue and nflog uses the
functions in nf_conntrack_netlink.o, put the conntrack attachment
basis into nf_conntrack_netlink.

On Wed, Aug 26, 2015 at 09:05:53PM +0200, Pablo Neira Ayuso wrote:
> On Tue, Aug 25, 2015 at 08:15:20AM +0900, Ken-ichirou MATSUZAWA wrote:
> >  config NETFILTER_NETLINK_QUEUE_CT
> > -        bool "NFQUEUE integration with Connection Tracking"
> > +        bool "NFQUEUE/NFLOG integration with Connection Tracking"
> >          default n
> > -        depends on NETFILTER_NETLINK_QUEUE
> > +        depends on NETFILTER_NETLINK_QUEUE || NETFILTER_NETLINK_LOG
> >  	help
> > -	  If this option is enabled, NFQUEUE can include Connection Tracking
> > -	  information together with the packet is the enqueued via NFNETLINK.
> > +	  If this option is enabled, NFQUEUE and/or NFLOG can include
> > +	  Connection Tracking information together with the packet is
> > +	  enqueued, logged via NFNETLINK.
> 
> You better add another Kconfig for _LOG.

That idea causes to expose functions in nf_netlink_queue_ct and to
disable to separate config in Kconfig too. Should I separate those
config? and would you please tell me how if I should?

Thanks,

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

* [PATCHv2 nf-next 1/5] netfilter: nfnetlink_queue: enable to specify nla type
  2015-09-01  0:34     ` Ken-ichirou MATSUZAWA
@ 2015-09-01  0:37       ` Ken-ichirou MATSUZAWA
  2015-09-01  0:39       ` [PATCHv2 nf-next 2/5] netfilter: nf_conntrack_netlink: rename to link ct attachment with Ken-ichirou MATSUZAWA
                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-09-01  0:37 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

This patch updates nfqnl_ct_put() signature to put not only queue
related attributes.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
---
 include/net/netfilter/nfnetlink_queue.h |    8 +++++---
 net/netfilter/nfnetlink_queue_core.c    |    2 +-
 net/netfilter/nfnetlink_queue_ct.c      |    9 +++++----
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h
index aff88ba..f94942b 100644
--- a/include/net/netfilter/nfnetlink_queue.h
+++ b/include/net/netfilter/nfnetlink_queue.h
@@ -11,8 +11,9 @@ struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
 struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
 			       const struct nlattr *attr,
 			       enum ip_conntrack_info *ctinfo);
-int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
-		 enum ip_conntrack_info ctinfo);
+int nfqnl_ct_put(struct sk_buff *skb,
+		 struct nf_conn *ct, int type,
+		 enum ip_conntrack_info ctinfo, int info_type);
 void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
 			 enum ip_conntrack_info ctinfo, int diff);
 int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
@@ -32,7 +33,8 @@ inline struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
 }
 
 inline int
-nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, int type,
+	     enum ip_conntrack_info ctinfo, int info_type)
 {
 	return 0;
 }
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 685cc6a..283a189 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -507,7 +507,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
 	if (seclen && nla_put(skb, NFQA_SECCTX, seclen, secdata))
 		goto nla_put_failure;
 
-	if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
+	if (ct && nfqnl_ct_put(skb, ct, NFQA_CT, ctinfo, NFQA_CT_INFO) < 0)
 		goto nla_put_failure;
 
 	if (cap_len > data_len &&
diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c
index 96cac50..2a30618 100644
--- a/net/netfilter/nfnetlink_queue_ct.c
+++ b/net/netfilter/nfnetlink_queue_ct.c
@@ -54,8 +54,9 @@ nfqnl_ct_parse(const struct sk_buff *skb, const struct nlattr *attr,
 	return ct;
 }
 
-int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
-		 enum ip_conntrack_info ctinfo)
+int nfqnl_ct_put(struct sk_buff *skb,
+		 struct nf_conn *ct, int type,
+		 enum ip_conntrack_info ctinfo, int info_type)
 {
 	struct nfq_ct_hook *nfq_ct;
 	struct nlattr *nest_parms;
@@ -65,7 +66,7 @@ int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
 	if (nfq_ct == NULL)
 		return 0;
 
-	nest_parms = nla_nest_start(skb, NFQA_CT | NLA_F_NESTED);
+	nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
 	if (!nest_parms)
 		goto nla_put_failure;
 
@@ -75,7 +76,7 @@ int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
 	nla_nest_end(skb, nest_parms);
 
 	tmp = ctinfo;
-	if (nla_put_be32(skb, NFQA_CT_INFO, htonl(tmp)))
+	if (nla_put_be32(skb, info_type, htonl(tmp)))
 		goto nla_put_failure;
 
 	return 0;
-- 
1.7.10.4


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

* [PATCHv2 nf-next 2/5] netfilter: nf_conntrack_netlink: rename to link ct attachment with
  2015-09-01  0:34     ` Ken-ichirou MATSUZAWA
  2015-09-01  0:37       ` [PATCHv2 nf-next 1/5] netfilter: nfnetlink_queue: enable to specify nla type Ken-ichirou MATSUZAWA
@ 2015-09-01  0:39       ` Ken-ichirou MATSUZAWA
  2015-09-01  0:41       ` [PATCHv2 nf-next 3/5] netfilter: nfnetlink_queue_ct: export functions Ken-ichirou MATSUZAWA
                         ` (2 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-09-01  0:39 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

This patch is the first pharse of which linking conntrack attach code
with nf_conntrack_netlink. The plan is intended to attach a conntrack
to nflog, based on what nfqueue has already done.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
---
 net/netfilter/Makefile                                                |    1 +
 net/netfilter/{nf_conntrack_netlink.c => nf_conntrack_netlink_core.c} |    0
 2 files changed, 1 insertion(+)
 rename net/netfilter/{nf_conntrack_netlink.c => nf_conntrack_netlink_core.c} (100%)

diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 70d026d..05a7746 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
 obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
 
 # netlink interface for nf_conntrack
+nf_conntrack_netlink-y := nf_conntrack_netlink_core.o
 obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
 obj-$(CONFIG_NF_CT_NETLINK_TIMEOUT) += nfnetlink_cttimeout.o
 obj-$(CONFIG_NF_CT_NETLINK_HELPER) += nfnetlink_cthelper.o
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink_core.c
similarity index 100%
rename from net/netfilter/nf_conntrack_netlink.c
rename to net/netfilter/nf_conntrack_netlink_core.c
-- 
1.7.10.4


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

* [PATCHv2 nf-next 3/5] netfilter: nfnetlink_queue_ct: export functions
  2015-09-01  0:34     ` Ken-ichirou MATSUZAWA
  2015-09-01  0:37       ` [PATCHv2 nf-next 1/5] netfilter: nfnetlink_queue: enable to specify nla type Ken-ichirou MATSUZAWA
  2015-09-01  0:39       ` [PATCHv2 nf-next 2/5] netfilter: nf_conntrack_netlink: rename to link ct attachment with Ken-ichirou MATSUZAWA
@ 2015-09-01  0:41       ` Ken-ichirou MATSUZAWA
  2015-09-03 10:10         ` Pablo Neira Ayuso
  2015-09-01  0:52       ` [PATCHv2 nf-next 4/5] netfilter: nfnetlink_queue: rename nfnetlink_queue_core.c Ken-ichirou MATSUZAWA
  2015-09-01  0:54       ` [PATCHv2 nf-next 5/5] netfilter: nfnetlink_log: allow to attach conntrack Ken-ichirou MATSUZAWA
  4 siblings, 1 reply; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-09-01  0:41 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

This patch exports functions in nfnetlink_queue_ct to use not only
from nfqueue, and move nfnetlink_queue_ct, conntrack attachement
basis, to nf_conntrack_netlink from nfnetlink_queue_core.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
---
 include/linux/netfilter.h                 |    1 -
 net/netfilter/Makefile                    |    2 +-
 net/netfilter/core.c                      |    3 ---
 net/netfilter/nf_conntrack_netlink_core.c |    3 +++
 net/netfilter/nfnetlink_queue_ct.c        |    7 +++++++
 5 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index d788ce6..b93422f 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -385,7 +385,6 @@ struct nfq_ct_hook {
 	void (*seq_adjust)(struct sk_buff *skb, struct nf_conn *ct,
 			   enum ip_conntrack_info ctinfo, s32 off);
 };
-extern struct nfq_ct_hook __rcu *nfq_ct_hook;
 #else
 static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
 #endif
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 05a7746..194dfa6 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_NETFILTER) = netfilter.o
 obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
 obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o
 nfnetlink_queue-y := nfnetlink_queue_core.o
-nfnetlink_queue-$(CONFIG_NETFILTER_NETLINK_QUEUE_CT) += nfnetlink_queue_ct.o
 obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
 obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
 
@@ -26,6 +25,7 @@ obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
 
 # netlink interface for nf_conntrack
 nf_conntrack_netlink-y := nf_conntrack_netlink_core.o
+nf_conntrack_netlink-$(CONFIG_NETFILTER_NETLINK_QUEUE_CT) += nfnetlink_queue_ct.o
 obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
 obj-$(CONFIG_NF_CT_NETLINK_TIMEOUT) += nfnetlink_cttimeout.o
 obj-$(CONFIG_NF_CT_NETLINK_HELPER) += nfnetlink_cthelper.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 0b939b7..aa68a76 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -385,9 +385,6 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
 }
 EXPORT_SYMBOL(nf_conntrack_destroy);
 
-struct nfq_ct_hook __rcu *nfq_ct_hook __read_mostly;
-EXPORT_SYMBOL_GPL(nfq_ct_hook);
-
 #endif /* CONFIG_NF_CONNTRACK */
 
 #ifdef CONFIG_NF_NAT_NEEDED
diff --git a/net/netfilter/nf_conntrack_netlink_core.c b/net/netfilter/nf_conntrack_netlink_core.c
index 94a6654..63e1f11 100644
--- a/net/netfilter/nf_conntrack_netlink_core.c
+++ b/net/netfilter/nf_conntrack_netlink_core.c
@@ -2134,6 +2134,9 @@ ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct,
 		       struct nf_conntrack_tuple *mask);
 
 #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
+
+extern struct nfq_ct_hook __rcu *nfq_ct_hook __read_mostly;
+
 static size_t
 ctnetlink_nfqueue_build_size(const struct nf_conn *ct)
 {
diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c
index 2a30618..299b5a8 100644
--- a/net/netfilter/nfnetlink_queue_ct.c
+++ b/net/netfilter/nfnetlink_queue_ct.c
@@ -14,6 +14,8 @@
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nfnetlink_queue.h>
 
+struct nfq_ct_hook __rcu *nfq_ct_hook __read_mostly;
+
 struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
 			     enum ip_conntrack_info *ctinfo)
 {
@@ -34,6 +36,7 @@ struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
 	}
 	return ct;
 }
+EXPORT_SYMBOL_GPL(nfqnl_ct_get);
 
 struct nf_conn *
 nfqnl_ct_parse(const struct sk_buff *skb, const struct nlattr *attr,
@@ -53,6 +56,7 @@ nfqnl_ct_parse(const struct sk_buff *skb, const struct nlattr *attr,
 
 	return ct;
 }
+EXPORT_SYMBOL_GPL(nfqnl_ct_parse);
 
 int nfqnl_ct_put(struct sk_buff *skb,
 		 struct nf_conn *ct, int type,
@@ -84,6 +88,7 @@ int nfqnl_ct_put(struct sk_buff *skb,
 nla_put_failure:
 	return -1;
 }
+EXPORT_SYMBOL_GPL(nfqnl_ct_put);
 
 void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
 			 enum ip_conntrack_info ctinfo, int diff)
@@ -97,6 +102,7 @@ void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
 	if ((ct->status & IPS_NAT_MASK) && diff)
 		nfq_ct->seq_adjust(skb, ct, ctinfo, diff);
 }
+EXPORT_SYMBOL_GPL(nfqnl_ct_seq_adjust);
 
 int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
 			u32 portid, u32 report)
@@ -112,3 +118,4 @@ int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
 
 	return nfq_ct->attach_expect(attr, ct, portid, report);
 }
+EXPORT_SYMBOL_GPL(nfqnl_attach_expect);
-- 
1.7.10.4


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

* [PATCHv2 nf-next 4/5] netfilter: nfnetlink_queue: rename nfnetlink_queue_core.c
  2015-09-01  0:34     ` Ken-ichirou MATSUZAWA
                         ` (2 preceding siblings ...)
  2015-09-01  0:41       ` [PATCHv2 nf-next 3/5] netfilter: nfnetlink_queue_ct: export functions Ken-ichirou MATSUZAWA
@ 2015-09-01  0:52       ` Ken-ichirou MATSUZAWA
  2015-09-01  0:54       ` [PATCHv2 nf-next 5/5] netfilter: nfnetlink_log: allow to attach conntrack Ken-ichirou MATSUZAWA
  4 siblings, 0 replies; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-09-01  0:52 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

Now conntrack attaching code belongs to nf_conntrack_core,
nfnetlink_queue_core can be renamed to old one.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
---
 net/netfilter/Makefile                                      |    1 -
 net/netfilter/{nfnetlink_queue_core.c => nfnetlink_queue.c} |    0
 2 files changed, 1 deletion(-)
 rename net/netfilter/{nfnetlink_queue_core.c => nfnetlink_queue.c} (100%)

diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 194dfa6..f2a456f 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_NETFILTER) = netfilter.o
 
 obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
 obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o
-nfnetlink_queue-y := nfnetlink_queue_core.o
 obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
 obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
 
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue.c
similarity index 100%
rename from net/netfilter/nfnetlink_queue_core.c
rename to net/netfilter/nfnetlink_queue.c
-- 
1.7.10.4


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

* [PATCHv2 nf-next 5/5] netfilter: nfnetlink_log: allow to attach conntrack
  2015-09-01  0:34     ` Ken-ichirou MATSUZAWA
                         ` (3 preceding siblings ...)
  2015-09-01  0:52       ` [PATCHv2 nf-next 4/5] netfilter: nfnetlink_queue: rename nfnetlink_queue_core.c Ken-ichirou MATSUZAWA
@ 2015-09-01  0:54       ` Ken-ichirou MATSUZAWA
  4 siblings, 0 replies; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-09-01  0:54 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

This patch enables to include the conntrack information together
with the packet that is sent to user-space via NFLOG, then a
user-space program can acquire NATed information by this NFULA_CT
attribute.

Including the conntrack information is optional, you can set it
via NFULNL_CFG_F_CONNTRACK flag with the NFULA_CFG_FLAGS attribute
like NFQUEUE.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
---
 include/net/netfilter/nfnetlink_queue.h      |    4 ++--
 include/uapi/linux/netfilter/nfnetlink_log.h |    3 +++
 net/netfilter/Kconfig                        |   12 +++++++-----
 net/netfilter/nfnetlink_log.c                |   18 +++++++++++++++---
 net/netfilter/nfnetlink_queue_ct.c           |    2 +-
 5 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h
index f94942b..05315ab 100644
--- a/include/net/netfilter/nfnetlink_queue.h
+++ b/include/net/netfilter/nfnetlink_queue.h
@@ -6,7 +6,7 @@
 struct nf_conn;
 
 #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
-struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
+struct nf_conn *nfqnl_ct_get(const struct sk_buff *entskb, size_t *size,
 			     enum ip_conntrack_info *ctinfo);
 struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
 			       const struct nlattr *attr,
@@ -20,7 +20,7 @@ int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
 			u32 portid, u32 report);
 #else
 inline struct nf_conn *
-nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
+nfqnl_ct_get(const struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
 {
 	return NULL;
 }
diff --git a/include/uapi/linux/netfilter/nfnetlink_log.h b/include/uapi/linux/netfilter/nfnetlink_log.h
index 90c2c95..081e7f9 100644
--- a/include/uapi/linux/netfilter/nfnetlink_log.h
+++ b/include/uapi/linux/netfilter/nfnetlink_log.h
@@ -51,6 +51,8 @@ enum nfulnl_attr_type {
 	NFULA_HWTYPE,			/* hardware type */
 	NFULA_HWHEADER,			/* hardware header */
 	NFULA_HWLEN,			/* hardware header length */
+	NFULA_CT,			/* nf_conntrack_netlink.h */
+	NFULA_CT_INFO,			/* enum ip_conntrack_info */
 
 	__NFULA_MAX
 };
@@ -93,5 +95,6 @@ enum nfulnl_attr_config {
 
 #define NFULNL_CFG_F_SEQ	0x0001
 #define NFULNL_CFG_F_SEQ_GLOBAL	0x0002
+#define NFULNL_CFG_F_CONNTRACK	0x0004
 
 #endif /* _NFNETLINK_LOG_H */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3e1b4ab..9c91cfa 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -363,12 +363,14 @@ config NF_CT_NETLINK_HELPER
 	  If unsure, say `N'.
 
 config NETFILTER_NETLINK_QUEUE_CT
-        bool "NFQUEUE integration with Connection Tracking"
-        default n
-        depends on NETFILTER_NETLINK_QUEUE
+	bool "NFQUEUE/NFLOG integration with Connection Tracking"
+	default n
+	depends on NF_CT_NETLINK
+	depends on NETFILTER_NETLINK_QUEUE || NETFILTER_NETLINK_LOG
 	help
-	  If this option is enabled, NFQUEUE can include Connection Tracking
-	  information together with the packet is the enqueued via NFNETLINK.
+	  If this option is enabled, NFQUEUE and NFLOG can include
+	  Connection Tracking information together with the packet is
+	  the enqueued via NFNETLINK.
 
 config NF_NAT
 	tristate
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 4670821..2ec2296 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -37,6 +37,7 @@
 #include <net/netfilter/nf_log.h>
 #include <net/netns/generic.h>
 #include <net/netfilter/nfnetlink_log.h>
+#include <net/netfilter/nfnetlink_queue.h>
 
 #include <linux/atomic.h>
 
@@ -401,7 +402,8 @@ __build_packet_message(struct nfnl_log_net *log,
 			unsigned int hooknum,
 			const struct net_device *indev,
 			const struct net_device *outdev,
-			const char *prefix, unsigned int plen)
+			const char *prefix, unsigned int plen,
+			struct nf_conn *ct, enum ip_conntrack_info ctinfo)
 {
 	struct nfulnl_msg_packet_hdr pmsg;
 	struct nlmsghdr *nlh;
@@ -575,6 +577,11 @@ __build_packet_message(struct nfnl_log_net *log,
 			 htonl(atomic_inc_return(&log->global_seq))))
 		goto nla_put_failure;
 
+	/* conntrack */
+	if (ct && nfqnl_ct_put(inst->skb, ct, NFULA_CT,
+			       ctinfo, NFULA_CT_INFO) < 0)
+		goto nla_put_failure;
+
 	if (data_len) {
 		struct nlattr *nla;
 		int size = nla_attr_size(data_len);
@@ -620,12 +627,15 @@ nfulnl_log_packet(struct net *net,
 		  const struct nf_loginfo *li_user,
 		  const char *prefix)
 {
-	unsigned int size, data_len;
+	size_t size;
+	unsigned int data_len;
 	struct nfulnl_instance *inst;
 	const struct nf_loginfo *li;
 	unsigned int qthreshold;
 	unsigned int plen;
 	struct nfnl_log_net *log = nfnl_log_pernet(net);
+	struct nf_conn *ct = NULL;
+	enum ip_conntrack_info uninitialized_var(ctinfo);
 
 	if (li_user && li_user->type == NF_LOG_TYPE_ULOG)
 		li = li_user;
@@ -671,6 +681,8 @@ nfulnl_log_packet(struct net *net,
 		size += nla_total_size(sizeof(u_int32_t));
 	if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
 		size += nla_total_size(sizeof(u_int32_t));
+	if (inst->flags & NFULNL_CFG_F_CONNTRACK)
+		ct = nfqnl_ct_get(skb, &size, &ctinfo);
 
 	qthreshold = inst->qthreshold;
 	/* per-rule qthreshold overrides per-instance */
@@ -715,7 +727,7 @@ nfulnl_log_packet(struct net *net,
 	inst->qlen++;
 
 	__build_packet_message(log, inst, skb, data_len, pf,
-				hooknum, in, out, prefix, plen);
+				hooknum, in, out, prefix, plen, ct, ctinfo);
 
 	if (inst->qlen >= qthreshold)
 		__nfulnl_flush(inst);
diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c
index 299b5a8..02d0dfd 100644
--- a/net/netfilter/nfnetlink_queue_ct.c
+++ b/net/netfilter/nfnetlink_queue_ct.c
@@ -16,7 +16,7 @@
 
 struct nfq_ct_hook __rcu *nfq_ct_hook __read_mostly;
 
-struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
+struct nf_conn *nfqnl_ct_get(const struct sk_buff *entskb, size_t *size,
 			     enum ip_conntrack_info *ctinfo)
 {
 	struct nfq_ct_hook *nfq_ct;
-- 
1.7.10.4


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

* Re: [PATCHv2 nf-next 3/5] netfilter: nfnetlink_queue_ct: export functions
  2015-09-01  0:41       ` [PATCHv2 nf-next 3/5] netfilter: nfnetlink_queue_ct: export functions Ken-ichirou MATSUZAWA
@ 2015-09-03 10:10         ` Pablo Neira Ayuso
  2015-09-07  7:44           ` Ken-ichirou MATSUZAWA
  0 siblings, 1 reply; 13+ messages in thread
From: Pablo Neira Ayuso @ 2015-09-03 10:10 UTC (permalink / raw)
  To: Ken-ichirou MATSUZAWA; +Cc: The netfilter developer mailinglist

On Tue, Sep 01, 2015 at 09:41:46AM +0900, Ken-ichirou MATSUZAWA wrote:
[...]
> diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c
> index 2a30618..299b5a8 100644
> --- a/net/netfilter/nfnetlink_queue_ct.c
> +++ b/net/netfilter/nfnetlink_queue_ct.c
> @@ -14,6 +14,8 @@
>  #include <net/netfilter/nf_conntrack.h>
>  #include <net/netfilter/nfnetlink_queue.h>
>  
> +struct nfq_ct_hook __rcu *nfq_ct_hook __read_mostly;
> +
>  struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
>  			     enum ip_conntrack_info *ctinfo)
>  {
> @@ -34,6 +36,7 @@ struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
>  	}
>  	return ct;
>  }
> +EXPORT_SYMBOL_GPL(nfqnl_ct_get);

After this patchset these functions are not nfqueue specific anymore,
so we have to place this in a single module, eg. nfnetlink_ct_glue.c
(unless someone comes up with a better name...).

The idea is that nfnetlink_queue and nfnetlink_log request this module
to be loaded when the CONNTRACK flag is passed.

The nfqnl_ prefix should be also modified, I'd suggest you use nfnl_ct_

Does this sound good to you?

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

* Re: [PATCHv2 nf-next 3/5] netfilter: nfnetlink_queue_ct: export functions
  2015-09-03 10:10         ` Pablo Neira Ayuso
@ 2015-09-07  7:44           ` Ken-ichirou MATSUZAWA
  0 siblings, 0 replies; 13+ messages in thread
From: Ken-ichirou MATSUZAWA @ 2015-09-07  7:44 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: The netfilter developer mailinglist

[-- Attachment #1: Type: text/plain, Size: 546 bytes --]

 Hi,

On Thu, Sep 03, 2015 at 12:10:34PM +0200, Pablo Neira Ayuso wrote:
> The idea is that nfnetlink_queue and nfnetlink_log request this module
> to be loaded when the CONNTRACK flag is passed.

I tried to modularize nfnetlink_queue_ct first, please see a patch
attached. It can be compiled with NETFILTER_NETLINK_QUEUE=m and any
of NETFILTER_NETLINK_QUEUE_CT, but in a case of QUEUE=y, QUEUE_CT
can not be a module.

Can we enforce QUEUE_CT not to be 'm', in case of QUEUE=y by
updating Kconfig? Would you please give me some advice?

Thanks,

[-- Attachment #2: 0001-netfilter-nfnetlink_queue-modularize-nfnetlink_queue.patch --]
[-- Type: text/x-diff, Size: 10041 bytes --]

>From e2bc33e98b8626c475482c11106e56d15bcf2268 Mon Sep 17 00:00:00 2001
From: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
Date: Mon, 7 Sep 2015 09:44:30 +0900
Subject: [PATCH 1/5] netfilter: nfnetlink_queue: modularize nfnetlink_queue_ct

The aim of this patch is eventually to include the conntrack
information together with not only nfqueue but also nflog. The first
thing to do so is modularize nfnetlink_queue_ct.

Signed-off-by: Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
---
 include/linux/netfilter.h               |   11 -----------
 include/net/netfilter/nf_conntrack.h    |   10 ++++++++++
 include/net/netfilter/nfnetlink_queue.h |    4 ++--
 net/netfilter/Kconfig                   |    7 ++++---
 net/netfilter/Makefile                  |    2 +-
 net/netfilter/core.c                    |    4 ----
 net/netfilter/nf_conntrack_netlink.c    |   12 +++---------
 net/netfilter/nfnetlink_queue_core.c    |    6 ++++++
 net/netfilter/nfnetlink_queue_ct.c      |   29 +++++++++++++++++++++++++++++
 9 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index d788ce6..5582d9b 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -375,17 +375,6 @@ extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu;
 struct nf_conn;
 enum ip_conntrack_info;
 struct nlattr;
-
-struct nfq_ct_hook {
-	size_t (*build_size)(const struct nf_conn *ct);
-	int (*build)(struct sk_buff *skb, struct nf_conn *ct);
-	int (*parse)(const struct nlattr *attr, struct nf_conn *ct);
-	int (*attach_expect)(const struct nlattr *attr, struct nf_conn *ct,
-			     u32 portid, u32 report);
-	void (*seq_adjust)(struct sk_buff *skb, struct nf_conn *ct,
-			   enum ip_conntrack_info ctinfo, s32 off);
-};
-extern struct nfq_ct_hook __rcu *nfq_ct_hook;
 #else
 static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
 #endif
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index f5e23c6..23d0528 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -305,4 +305,14 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
 #define MODULE_ALIAS_NFCT_HELPER(helper) \
         MODULE_ALIAS("nfct-helper-" helper)
 
+struct nfq_ct_hook {
+	size_t (*build_size)(const struct nf_conn *ct);
+	int (*build)(struct sk_buff *skb, struct nf_conn *ct);
+	int (*parse)(const struct nlattr *attr, struct nf_conn *ct);
+	int (*attach_expect)(const struct nlattr *attr, struct nf_conn *ct,
+			     u32 portid, u32 report);
+	void (*seq_adjust)(struct sk_buff *skb, struct nf_conn *ct,
+			   enum ip_conntrack_info ctinfo, s32 off);
+};
+
 #endif /* _NF_CONNTRACK_H */
diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h
index aff88ba..def25ad 100644
--- a/include/net/netfilter/nfnetlink_queue.h
+++ b/include/net/netfilter/nfnetlink_queue.h
@@ -5,7 +5,7 @@
 
 struct nf_conn;
 
-#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
+#if IS_ENABLED(CONFIG_NETFILTER_NETLINK_QUEUE_CT)
 struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
 			     enum ip_conntrack_info *ctinfo);
 struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
@@ -47,5 +47,5 @@ inline int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
 {
 	return 0;
 }
-#endif /* NF_CONNTRACK */
+#endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */
 #endif
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3e1b4ab..b11e198 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -363,9 +363,10 @@ config NF_CT_NETLINK_HELPER
 	  If unsure, say `N'.
 
 config NETFILTER_NETLINK_QUEUE_CT
-        bool "NFQUEUE integration with Connection Tracking"
-        default n
-        depends on NETFILTER_NETLINK_QUEUE
+	tristate "NFQUEUE integration with Connection Tracking"
+	default n
+	depends on NF_CT_NETLINK
+	depends on NETFILTER_NETLINK_QUEUE
 	help
 	  If this option is enabled, NFQUEUE can include Connection Tracking
 	  information together with the packet is the enqueued via NFNETLINK.
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 70d026d..701d548 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -11,9 +11,9 @@ obj-$(CONFIG_NETFILTER) = netfilter.o
 obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
 obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o
 nfnetlink_queue-y := nfnetlink_queue_core.o
-nfnetlink_queue-$(CONFIG_NETFILTER_NETLINK_QUEUE_CT) += nfnetlink_queue_ct.o
 obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
 obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
+obj-$(CONFIG_NETFILTER_NETLINK_QUEUE_CT) += nfnetlink_queue_ct.o
 
 # connection tracking
 obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 0b939b7..31be279 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -384,10 +384,6 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
 	rcu_read_unlock();
 }
 EXPORT_SYMBOL(nf_conntrack_destroy);
-
-struct nfq_ct_hook __rcu *nfq_ct_hook __read_mostly;
-EXPORT_SYMBOL_GPL(nfq_ct_hook);
-
 #endif /* CONFIG_NF_CONNTRACK */
 
 #ifdef CONFIG_NF_NAT_NEEDED
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 94a6654..bd355a5 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2133,7 +2133,7 @@ ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct,
 		       struct nf_conntrack_tuple *tuple,
 		       struct nf_conntrack_tuple *mask);
 
-#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
+#if IS_ENABLED(CONFIG_NETFILTER_NETLINK_QUEUE_CT)
 static size_t
 ctnetlink_nfqueue_build_size(const struct nf_conn *ct)
 {
@@ -2350,13 +2350,14 @@ ctnetlink_nfqueue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
 	return 0;
 }
 
-static struct nfq_ct_hook ctnetlink_nfqueue_hook = {
+struct nfq_ct_hook ctnetlink_nfqueue_hook = {
 	.build_size	= ctnetlink_nfqueue_build_size,
 	.build		= ctnetlink_nfqueue_build,
 	.parse		= ctnetlink_nfqueue_parse,
 	.attach_expect	= ctnetlink_nfqueue_attach_expect,
 	.seq_adjust	= nf_ct_tcp_seqadj_set,
 };
+EXPORT_SYMBOL_GPL(ctnetlink_nfqueue_hook);
 #endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */
 
 /***********************************************************************
@@ -3341,10 +3342,6 @@ static int __init ctnetlink_init(void)
 		pr_err("ctnetlink_init: cannot register pernet operations\n");
 		goto err_unreg_exp_subsys;
 	}
-#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
-	/* setup interaction between nf_queue and nf_conntrack_netlink. */
-	RCU_INIT_POINTER(nfq_ct_hook, &ctnetlink_nfqueue_hook);
-#endif
 	return 0;
 
 err_unreg_exp_subsys:
@@ -3362,9 +3359,6 @@ static void __exit ctnetlink_exit(void)
 	unregister_pernet_subsys(&ctnetlink_net_ops);
 	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
 	nfnetlink_subsys_unregister(&ctnl_subsys);
-#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
-	RCU_INIT_POINTER(nfq_ct_hook, NULL);
-#endif
 }
 
 module_init(ctnetlink_init);
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 685cc6a..e2bca3a 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -1196,6 +1196,12 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
 			goto err_out_unlock;
 		}
 #endif
+#if !IS_ENABLED(CONFIG_NETFILTER_NETLINK_QUEUE_CT)
+		if (flags & mask & NFQA_CFG_F_CONNTRACK) {
+			ret = -EOPNOTSUPP;
+			goto err_out_unlock;
+		}
+#endif
 		spin_lock_bh(&queue->lock);
 		queue->flags &= ~mask;
 		queue->flags |= flags & mask;
diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c
index 96cac50..4e8587e 100644
--- a/net/netfilter/nfnetlink_queue_ct.c
+++ b/net/netfilter/nfnetlink_queue_ct.c
@@ -7,6 +7,9 @@
  *
  */
 
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter/nfnetlink.h>
@@ -14,6 +17,9 @@
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nfnetlink_queue.h>
 
+extern struct nfq_ct_hook ctnetlink_nfqueue_hook;
+static struct nfq_ct_hook __rcu *nfq_ct_hook __read_mostly;
+
 struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
 			     enum ip_conntrack_info *ctinfo)
 {
@@ -34,6 +40,7 @@ struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
 	}
 	return ct;
 }
+EXPORT_SYMBOL_GPL(nfqnl_ct_get);
 
 struct nf_conn *
 nfqnl_ct_parse(const struct sk_buff *skb, const struct nlattr *attr,
@@ -53,6 +60,7 @@ nfqnl_ct_parse(const struct sk_buff *skb, const struct nlattr *attr,
 
 	return ct;
 }
+EXPORT_SYMBOL_GPL(nfqnl_ct_parse);
 
 int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
 		 enum ip_conntrack_info ctinfo)
@@ -83,6 +91,7 @@ int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
 nla_put_failure:
 	return -1;
 }
+EXPORT_SYMBOL_GPL(nfqnl_ct_put);
 
 void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
 			 enum ip_conntrack_info ctinfo, int diff)
@@ -96,6 +105,7 @@ void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
 	if ((ct->status & IPS_NAT_MASK) && diff)
 		nfq_ct->seq_adjust(skb, ct, ctinfo, diff);
 }
+EXPORT_SYMBOL_GPL(nfqnl_ct_seq_adjust);
 
 int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
 			u32 portid, u32 report)
@@ -111,3 +121,22 @@ int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
 
 	return nfq_ct->attach_expect(attr, ct, portid, report);
 }
+EXPORT_SYMBOL_GPL(nfqnl_attach_expect);
+
+static int __init nfnl_glue_ct_init(void)
+{
+	rcu_assign_pointer(nfq_ct_hook, &ctnetlink_nfqueue_hook);
+	return 0;
+}
+
+static void __exit nfnl_glue_ct_exit(void)
+{
+	RCU_INIT_POINTER(nfq_ct_hook, NULL);
+        synchronize_rcu();
+}
+
+module_init(nfnl_glue_ct_init);
+module_exit(nfnl_glue_ct_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
-- 
1.7.10.4


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

end of thread, other threads:[~2015-09-07  7:44 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-24 23:10 [PATCH nf-next 0/2] netfilter: nfnetlink_log attach conntrack Ken-ichirou MATSUZAWA
2015-08-24 23:13 ` [PATCH nf-next 1/2] netfilter: nfnetlink_queue: enable to specify nla type Ken-ichirou MATSUZAWA
2015-08-24 23:15 ` [PATCH nf-next 2/2] netfilter: nfnetlink_log: allow to attach conntrack Ken-ichirou MATSUZAWA
2015-08-26 19:05   ` Pablo Neira Ayuso
2015-08-28  6:43     ` Ken-ichirou MATSUZAWA
2015-09-01  0:34     ` Ken-ichirou MATSUZAWA
2015-09-01  0:37       ` [PATCHv2 nf-next 1/5] netfilter: nfnetlink_queue: enable to specify nla type Ken-ichirou MATSUZAWA
2015-09-01  0:39       ` [PATCHv2 nf-next 2/5] netfilter: nf_conntrack_netlink: rename to link ct attachment with Ken-ichirou MATSUZAWA
2015-09-01  0:41       ` [PATCHv2 nf-next 3/5] netfilter: nfnetlink_queue_ct: export functions Ken-ichirou MATSUZAWA
2015-09-03 10:10         ` Pablo Neira Ayuso
2015-09-07  7:44           ` Ken-ichirou MATSUZAWA
2015-09-01  0:52       ` [PATCHv2 nf-next 4/5] netfilter: nfnetlink_queue: rename nfnetlink_queue_core.c Ken-ichirou MATSUZAWA
2015-09-01  0:54       ` [PATCHv2 nf-next 5/5] netfilter: nfnetlink_log: allow to attach conntrack Ken-ichirou MATSUZAWA

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).