linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6] Netfilter ring buffer support
@ 2012-03-05 23:19 Richard Weinberger
  2012-03-05 23:19 ` [PATCH 1/6] Netfilter: Merge ipt_LOG and ip6_LOG into xt_LOG Richard Weinberger
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: Richard Weinberger @ 2012-03-05 23:19 UTC (permalink / raw)
  To: pablo
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel, rostedt

This patch set merges ipt_LOG and ip6t_LOG and adds ring buffer support
to xt_LOG.

Using "--ring" an user can create LOG rules which log messages into
one or more ring buffers.
Each ring buffer is represented as pipe-like file in
/proc/net/netfilter/nf_log_ring/.

Ring buffer support can be enabled/disabled using
CONFIG_NETFILTER_XT_TARGET_LOG_RING.

Changes since v1:
 - Merged ipt_LOG and ip6t_LOG
 - Implemented ring buffer support as part of xt_LOG.

Changes since v2:
 - Fixed struct xt_log_info_v1's data layout
 - Removed the sizeof(void *) hack
 - Replaced BUG() by WARN_ON_ONCE()

Changes since v3:
 - Merged xt_LOG_core.c and xt_LOG_ring.c into xt_LOG.c
 - Made checkpatch.pl happy

Changes since v4:
 - Fixed a typo in include/linux/netfilter/Kbuild
   (Thanks Bastian!)

Changes since v5:
 - Made timestamp support a separate patch
 - Renamed xt_LOG_ring to nf_log_ring
 - Removed unused prototypes from xt_log.h
 - Renamed find_next_entry_inc() to find_next_iter_entry()
 - Fixed OOM error path in rlog_open_pipe()

Patch 1 and 2 have already been applied to net-next.git.

[PATCH 1/6] Netfilter: Merge ipt_LOG and ip6_LOG into xt_LOG
[PATCH 2/6] netfilter: xt_LOG: fix bogus extra layer-4 logging
[PATCH 3/6] ring_buffer: Export for_each_buffer_cpu()
[PATCH 4/6] xt_log: Make printk() in sb_close() optional
[PATCH 5/6] Netfilter: xt_LOG: Implement ring buffer support
[PATCH 6/6] Netfilter: xt_LOG: Add timestamp support

Thanks,
//richard

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

* [PATCH 1/6] Netfilter: Merge ipt_LOG and ip6_LOG into xt_LOG
  2012-03-05 23:19 [PATCH v6] Netfilter ring buffer support Richard Weinberger
@ 2012-03-05 23:19 ` Richard Weinberger
  2012-03-05 23:19 ` [PATCH 2/6] netfilter: xt_LOG: fix bogus extra layer-4 logging information Richard Weinberger
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Richard Weinberger @ 2012-03-05 23:19 UTC (permalink / raw)
  To: pablo
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel,
	rostedt, Richard Weinberger

ipt_LOG and ip6_LOG have a lot of common code, merge them
to reduce duplicate code.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/linux/netfilter/Kbuild          |    1 +
 include/linux/netfilter/xt_LOG.h        |   19 +
 include/linux/netfilter_ipv4/ipt_LOG.h  |    2 +
 include/linux/netfilter_ipv6/ip6t_LOG.h |    2 +
 net/ipv4/netfilter/Kconfig              |    9 -
 net/ipv4/netfilter/Makefile             |    1 -
 net/ipv4/netfilter/ipt_LOG.c            |  516 -----------------
 net/ipv6/netfilter/Kconfig              |    9 -
 net/ipv6/netfilter/Makefile             |    1 -
 net/ipv6/netfilter/ip6t_LOG.c           |  527 ------------------
 net/netfilter/Kconfig                   |    9 +
 net/netfilter/Makefile                  |    1 +
 net/netfilter/xt_LOG.c                  |  921 +++++++++++++++++++++++++++++++
 13 files changed, 955 insertions(+), 1063 deletions(-)
 create mode 100644 include/linux/netfilter/xt_LOG.h
 delete mode 100644 net/ipv4/netfilter/ipt_LOG.c
 delete mode 100644 net/ipv6/netfilter/ip6t_LOG.c
 create mode 100644 net/netfilter/xt_LOG.c

diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index e144f54..aaa72aa 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -22,6 +22,7 @@ header-y += xt_CT.h
 header-y += xt_DSCP.h
 header-y += xt_IDLETIMER.h
 header-y += xt_LED.h
+header-y += xt_LOG.h
 header-y += xt_MARK.h
 header-y += xt_nfacct.h
 header-y += xt_NFLOG.h
diff --git a/include/linux/netfilter/xt_LOG.h b/include/linux/netfilter/xt_LOG.h
new file mode 100644
index 0000000..cac0790
--- /dev/null
+++ b/include/linux/netfilter/xt_LOG.h
@@ -0,0 +1,19 @@
+#ifndef _XT_LOG_H
+#define _XT_LOG_H
+
+/* make sure not to change this without changing nf_log.h:NF_LOG_* (!) */
+#define XT_LOG_TCPSEQ		0x01	/* Log TCP sequence numbers */
+#define XT_LOG_TCPOPT		0x02	/* Log TCP options */
+#define XT_LOG_IPOPT		0x04	/* Log IP options */
+#define XT_LOG_UID		0x08	/* Log UID owning local socket */
+#define XT_LOG_NFLOG		0x10	/* Unsupported, don't reuse */
+#define XT_LOG_MACDECODE	0x20	/* Decode MAC header */
+#define XT_LOG_MASK		0x2f
+
+struct xt_log_info {
+	unsigned char level;
+	unsigned char logflags;
+	char prefix[30];
+};
+
+#endif /* _XT_LOG_H */
diff --git a/include/linux/netfilter_ipv4/ipt_LOG.h b/include/linux/netfilter_ipv4/ipt_LOG.h
index dcdbadf..5d81520 100644
--- a/include/linux/netfilter_ipv4/ipt_LOG.h
+++ b/include/linux/netfilter_ipv4/ipt_LOG.h
@@ -1,6 +1,8 @@
 #ifndef _IPT_LOG_H
 #define _IPT_LOG_H
 
+#warning "Please update iptables, this file will be removed soon!"
+
 /* make sure not to change this without changing netfilter.h:NF_LOG_* (!) */
 #define IPT_LOG_TCPSEQ		0x01	/* Log TCP sequence numbers */
 #define IPT_LOG_TCPOPT		0x02	/* Log TCP options */
diff --git a/include/linux/netfilter_ipv6/ip6t_LOG.h b/include/linux/netfilter_ipv6/ip6t_LOG.h
index 9dd5579..3dd0bc4 100644
--- a/include/linux/netfilter_ipv6/ip6t_LOG.h
+++ b/include/linux/netfilter_ipv6/ip6t_LOG.h
@@ -1,6 +1,8 @@
 #ifndef _IP6T_LOG_H
 #define _IP6T_LOG_H
 
+#warning "Please update iptables, this file will be removed soon!"
+
 /* make sure not to change this without changing netfilter.h:NF_LOG_* (!) */
 #define IP6T_LOG_TCPSEQ		0x01	/* Log TCP sequence numbers */
 #define IP6T_LOG_TCPOPT		0x02	/* Log TCP options */
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 74dfc9e..fcc543c 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -123,15 +123,6 @@ config IP_NF_TARGET_REJECT
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_TARGET_LOG
-	tristate "LOG target support"
-	default m if NETFILTER_ADVANCED=n
-	help
-	  This option adds a `LOG' target, which allows you to create rules in
-	  any iptables table which records the packet header to the syslog.
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
 config IP_NF_TARGET_ULOG
 	tristate "ULOG target support"
 	default m if NETFILTER_ADVANCED=n
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 213a462..240b684 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -54,7 +54,6 @@ obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o
 # targets
 obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
-obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
deleted file mode 100644
index d76d6c9..0000000
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * This is a module which is used for logging packets.
- */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@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/spinlock.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/ip.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/tcp.h>
-#include <net/route.h>
-
-#include <linux/netfilter.h>
-#include <linux/netfilter/x_tables.h>
-#include <linux/netfilter_ipv4/ipt_LOG.h>
-#include <net/netfilter/nf_log.h>
-#include <net/netfilter/xt_log.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("Xtables: IPv4 packet logging to syslog");
-
-/* One level of recursion won't kill us */
-static void dump_packet(struct sbuff *m,
-			const struct nf_loginfo *info,
-			const struct sk_buff *skb,
-			unsigned int iphoff)
-{
-	struct iphdr _iph;
-	const struct iphdr *ih;
-	unsigned int logflags;
-
-	if (info->type == NF_LOG_TYPE_LOG)
-		logflags = info->u.log.logflags;
-	else
-		logflags = NF_LOG_MASK;
-
-	ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
-	if (ih == NULL) {
-		sb_add(m, "TRUNCATED");
-		return;
-	}
-
-	/* Important fields:
-	 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
-	/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
-	sb_add(m, "SRC=%pI4 DST=%pI4 ",
-	       &ih->saddr, &ih->daddr);
-
-	/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
-	sb_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
-	       ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
-	       ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
-
-	/* Max length: 6 "CE DF MF " */
-	if (ntohs(ih->frag_off) & IP_CE)
-		sb_add(m, "CE ");
-	if (ntohs(ih->frag_off) & IP_DF)
-		sb_add(m, "DF ");
-	if (ntohs(ih->frag_off) & IP_MF)
-		sb_add(m, "MF ");
-
-	/* Max length: 11 "FRAG:65535 " */
-	if (ntohs(ih->frag_off) & IP_OFFSET)
-		sb_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
-
-	if ((logflags & IPT_LOG_IPOPT) &&
-	    ih->ihl * 4 > sizeof(struct iphdr)) {
-		const unsigned char *op;
-		unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
-		unsigned int i, optsize;
-
-		optsize = ih->ihl * 4 - sizeof(struct iphdr);
-		op = skb_header_pointer(skb, iphoff+sizeof(_iph),
-					optsize, _opt);
-		if (op == NULL) {
-			sb_add(m, "TRUNCATED");
-			return;
-		}
-
-		/* Max length: 127 "OPT (" 15*4*2chars ") " */
-		sb_add(m, "OPT (");
-		for (i = 0; i < optsize; i++)
-			sb_add(m, "%02X", op[i]);
-		sb_add(m, ") ");
-	}
-
-	switch (ih->protocol) {
-	case IPPROTO_TCP: {
-		struct tcphdr _tcph;
-		const struct tcphdr *th;
-
-		/* Max length: 10 "PROTO=TCP " */
-		sb_add(m, "PROTO=TCP ");
-
-		if (ntohs(ih->frag_off) & IP_OFFSET)
-			break;
-
-		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		th = skb_header_pointer(skb, iphoff + ih->ihl * 4,
-					sizeof(_tcph), &_tcph);
-		if (th == NULL) {
-			sb_add(m, "INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - ih->ihl*4);
-			break;
-		}
-
-		/* Max length: 20 "SPT=65535 DPT=65535 " */
-		sb_add(m, "SPT=%u DPT=%u ",
-		       ntohs(th->source), ntohs(th->dest));
-		/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
-		if (logflags & IPT_LOG_TCPSEQ)
-			sb_add(m, "SEQ=%u ACK=%u ",
-			       ntohl(th->seq), ntohl(th->ack_seq));
-		/* Max length: 13 "WINDOW=65535 " */
-		sb_add(m, "WINDOW=%u ", ntohs(th->window));
-		/* Max length: 9 "RES=0x3F " */
-		sb_add(m, "RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
-		/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
-		if (th->cwr)
-			sb_add(m, "CWR ");
-		if (th->ece)
-			sb_add(m, "ECE ");
-		if (th->urg)
-			sb_add(m, "URG ");
-		if (th->ack)
-			sb_add(m, "ACK ");
-		if (th->psh)
-			sb_add(m, "PSH ");
-		if (th->rst)
-			sb_add(m, "RST ");
-		if (th->syn)
-			sb_add(m, "SYN ");
-		if (th->fin)
-			sb_add(m, "FIN ");
-		/* Max length: 11 "URGP=65535 " */
-		sb_add(m, "URGP=%u ", ntohs(th->urg_ptr));
-
-		if ((logflags & IPT_LOG_TCPOPT) &&
-		    th->doff * 4 > sizeof(struct tcphdr)) {
-			unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
-			const unsigned char *op;
-			unsigned int i, optsize;
-
-			optsize = th->doff * 4 - sizeof(struct tcphdr);
-			op = skb_header_pointer(skb,
-						iphoff+ih->ihl*4+sizeof(_tcph),
-						optsize, _opt);
-			if (op == NULL) {
-				sb_add(m, "TRUNCATED");
-				return;
-			}
-
-			/* Max length: 127 "OPT (" 15*4*2chars ") " */
-			sb_add(m, "OPT (");
-			for (i = 0; i < optsize; i++)
-				sb_add(m, "%02X", op[i]);
-			sb_add(m, ") ");
-		}
-		break;
-	}
-	case IPPROTO_UDP:
-	case IPPROTO_UDPLITE: {
-		struct udphdr _udph;
-		const struct udphdr *uh;
-
-		if (ih->protocol == IPPROTO_UDP)
-			/* Max length: 10 "PROTO=UDP "     */
-			sb_add(m, "PROTO=UDP " );
-		else	/* Max length: 14 "PROTO=UDPLITE " */
-			sb_add(m, "PROTO=UDPLITE ");
-
-		if (ntohs(ih->frag_off) & IP_OFFSET)
-			break;
-
-		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		uh = skb_header_pointer(skb, iphoff+ih->ihl*4,
-					sizeof(_udph), &_udph);
-		if (uh == NULL) {
-			sb_add(m, "INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - ih->ihl*4);
-			break;
-		}
-
-		/* Max length: 20 "SPT=65535 DPT=65535 " */
-		sb_add(m, "SPT=%u DPT=%u LEN=%u ",
-		       ntohs(uh->source), ntohs(uh->dest),
-		       ntohs(uh->len));
-		break;
-	}
-	case IPPROTO_ICMP: {
-		struct icmphdr _icmph;
-		const struct icmphdr *ich;
-		static const size_t required_len[NR_ICMP_TYPES+1]
-			= { [ICMP_ECHOREPLY] = 4,
-			    [ICMP_DEST_UNREACH]
-			    = 8 + sizeof(struct iphdr),
-			    [ICMP_SOURCE_QUENCH]
-			    = 8 + sizeof(struct iphdr),
-			    [ICMP_REDIRECT]
-			    = 8 + sizeof(struct iphdr),
-			    [ICMP_ECHO] = 4,
-			    [ICMP_TIME_EXCEEDED]
-			    = 8 + sizeof(struct iphdr),
-			    [ICMP_PARAMETERPROB]
-			    = 8 + sizeof(struct iphdr),
-			    [ICMP_TIMESTAMP] = 20,
-			    [ICMP_TIMESTAMPREPLY] = 20,
-			    [ICMP_ADDRESS] = 12,
-			    [ICMP_ADDRESSREPLY] = 12 };
-
-		/* Max length: 11 "PROTO=ICMP " */
-		sb_add(m, "PROTO=ICMP ");
-
-		if (ntohs(ih->frag_off) & IP_OFFSET)
-			break;
-
-		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
-					 sizeof(_icmph), &_icmph);
-		if (ich == NULL) {
-			sb_add(m, "INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - ih->ihl*4);
-			break;
-		}
-
-		/* Max length: 18 "TYPE=255 CODE=255 " */
-		sb_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code);
-
-		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (ich->type <= NR_ICMP_TYPES &&
-		    required_len[ich->type] &&
-		    skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
-			sb_add(m, "INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - ih->ihl*4);
-			break;
-		}
-
-		switch (ich->type) {
-		case ICMP_ECHOREPLY:
-		case ICMP_ECHO:
-			/* Max length: 19 "ID=65535 SEQ=65535 " */
-			sb_add(m, "ID=%u SEQ=%u ",
-			       ntohs(ich->un.echo.id),
-			       ntohs(ich->un.echo.sequence));
-			break;
-
-		case ICMP_PARAMETERPROB:
-			/* Max length: 14 "PARAMETER=255 " */
-			sb_add(m, "PARAMETER=%u ",
-			       ntohl(ich->un.gateway) >> 24);
-			break;
-		case ICMP_REDIRECT:
-			/* Max length: 24 "GATEWAY=255.255.255.255 " */
-			sb_add(m, "GATEWAY=%pI4 ", &ich->un.gateway);
-			/* Fall through */
-		case ICMP_DEST_UNREACH:
-		case ICMP_SOURCE_QUENCH:
-		case ICMP_TIME_EXCEEDED:
-			/* Max length: 3+maxlen */
-			if (!iphoff) { /* Only recurse once. */
-				sb_add(m, "[");
-				dump_packet(m, info, skb,
-					    iphoff + ih->ihl*4+sizeof(_icmph));
-				sb_add(m, "] ");
-			}
-
-			/* Max length: 10 "MTU=65535 " */
-			if (ich->type == ICMP_DEST_UNREACH &&
-			    ich->code == ICMP_FRAG_NEEDED)
-				sb_add(m, "MTU=%u ", ntohs(ich->un.frag.mtu));
-		}
-		break;
-	}
-	/* Max Length */
-	case IPPROTO_AH: {
-		struct ip_auth_hdr _ahdr;
-		const struct ip_auth_hdr *ah;
-
-		if (ntohs(ih->frag_off) & IP_OFFSET)
-			break;
-
-		/* Max length: 9 "PROTO=AH " */
-		sb_add(m, "PROTO=AH ");
-
-		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
-					sizeof(_ahdr), &_ahdr);
-		if (ah == NULL) {
-			sb_add(m, "INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - ih->ihl*4);
-			break;
-		}
-
-		/* Length: 15 "SPI=0xF1234567 " */
-		sb_add(m, "SPI=0x%x ", ntohl(ah->spi));
-		break;
-	}
-	case IPPROTO_ESP: {
-		struct ip_esp_hdr _esph;
-		const struct ip_esp_hdr *eh;
-
-		/* Max length: 10 "PROTO=ESP " */
-		sb_add(m, "PROTO=ESP ");
-
-		if (ntohs(ih->frag_off) & IP_OFFSET)
-			break;
-
-		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
-					sizeof(_esph), &_esph);
-		if (eh == NULL) {
-			sb_add(m, "INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - ih->ihl*4);
-			break;
-		}
-
-		/* Length: 15 "SPI=0xF1234567 " */
-		sb_add(m, "SPI=0x%x ", ntohl(eh->spi));
-		break;
-	}
-	/* Max length: 10 "PROTO 255 " */
-	default:
-		sb_add(m, "PROTO=%u ", ih->protocol);
-	}
-
-	/* Max length: 15 "UID=4294967295 " */
-	if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
-		read_lock_bh(&skb->sk->sk_callback_lock);
-		if (skb->sk->sk_socket && skb->sk->sk_socket->file)
-			sb_add(m, "UID=%u GID=%u ",
-				skb->sk->sk_socket->file->f_cred->fsuid,
-				skb->sk->sk_socket->file->f_cred->fsgid);
-		read_unlock_bh(&skb->sk->sk_callback_lock);
-	}
-
-	/* Max length: 16 "MARK=0xFFFFFFFF " */
-	if (!iphoff && skb->mark)
-		sb_add(m, "MARK=0x%x ", skb->mark);
-
-	/* Proto    Max log string length */
-	/* IP:      40+46+6+11+127 = 230 */
-	/* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
-	/* UDP:     10+max(25,20) = 35 */
-	/* UDPLITE: 14+max(25,20) = 39 */
-	/* ICMP:    11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
-	/* ESP:     10+max(25)+15 = 50 */
-	/* AH:      9+max(25)+15 = 49 */
-	/* unknown: 10 */
-
-	/* (ICMP allows recursion one level deep) */
-	/* maxlen =  IP + ICMP +  IP + max(TCP,UDP,ICMP,unknown) */
-	/* maxlen = 230+   91  + 230 + 252 = 803 */
-}
-
-static void dump_mac_header(struct sbuff *m,
-			    const struct nf_loginfo *info,
-			    const struct sk_buff *skb)
-{
-	struct net_device *dev = skb->dev;
-	unsigned int logflags = 0;
-
-	if (info->type == NF_LOG_TYPE_LOG)
-		logflags = info->u.log.logflags;
-
-	if (!(logflags & IPT_LOG_MACDECODE))
-		goto fallback;
-
-	switch (dev->type) {
-	case ARPHRD_ETHER:
-		sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
-		       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
-		       ntohs(eth_hdr(skb)->h_proto));
-		return;
-	default:
-		break;
-	}
-
-fallback:
-	sb_add(m, "MAC=");
-	if (dev->hard_header_len &&
-	    skb->mac_header != skb->network_header) {
-		const unsigned char *p = skb_mac_header(skb);
-		unsigned int i;
-
-		sb_add(m, "%02x", *p++);
-		for (i = 1; i < dev->hard_header_len; i++, p++)
-			sb_add(m, ":%02x", *p);
-	}
-	sb_add(m, " ");
-}
-
-static struct nf_loginfo default_loginfo = {
-	.type	= NF_LOG_TYPE_LOG,
-	.u = {
-		.log = {
-			.level    = 5,
-			.logflags = NF_LOG_MASK,
-		},
-	},
-};
-
-static void
-ipt_log_packet(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 *loginfo,
-	       const char *prefix)
-{
-	struct sbuff *m = sb_open();
-
-	if (!loginfo)
-		loginfo = &default_loginfo;
-
-	sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
-	       prefix,
-	       in ? in->name : "",
-	       out ? out->name : "");
-#ifdef CONFIG_BRIDGE_NETFILTER
-	if (skb->nf_bridge) {
-		const struct net_device *physindev;
-		const struct net_device *physoutdev;
-
-		physindev = skb->nf_bridge->physindev;
-		if (physindev && in != physindev)
-			sb_add(m, "PHYSIN=%s ", physindev->name);
-		physoutdev = skb->nf_bridge->physoutdev;
-		if (physoutdev && out != physoutdev)
-			sb_add(m, "PHYSOUT=%s ", physoutdev->name);
-	}
-#endif
-
-	if (in != NULL)
-		dump_mac_header(m, loginfo, skb);
-
-	dump_packet(m, loginfo, skb, 0);
-
-	sb_close(m);
-}
-
-static unsigned int
-log_tg(struct sk_buff *skb, const struct xt_action_param *par)
-{
-	const struct ipt_log_info *loginfo = par->targinfo;
-	struct nf_loginfo li;
-
-	li.type = NF_LOG_TYPE_LOG;
-	li.u.log.level = loginfo->level;
-	li.u.log.logflags = loginfo->logflags;
-
-	ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, par->out, &li,
-		       loginfo->prefix);
-	return XT_CONTINUE;
-}
-
-static int log_tg_check(const struct xt_tgchk_param *par)
-{
-	const struct ipt_log_info *loginfo = par->targinfo;
-
-	if (loginfo->level >= 8) {
-		pr_debug("level %u >= 8\n", loginfo->level);
-		return -EINVAL;
-	}
-	if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
-		pr_debug("prefix is not null-terminated\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static struct xt_target log_tg_reg __read_mostly = {
-	.name		= "LOG",
-	.family		= NFPROTO_IPV4,
-	.target		= log_tg,
-	.targetsize	= sizeof(struct ipt_log_info),
-	.checkentry	= log_tg_check,
-	.me		= THIS_MODULE,
-};
-
-static struct nf_logger ipt_log_logger __read_mostly = {
-	.name		= "ipt_LOG",
-	.logfn		= &ipt_log_packet,
-	.me		= THIS_MODULE,
-};
-
-static int __init log_tg_init(void)
-{
-	int ret;
-
-	ret = xt_register_target(&log_tg_reg);
-	if (ret < 0)
-		return ret;
-	nf_log_register(NFPROTO_IPV4, &ipt_log_logger);
-	return 0;
-}
-
-static void __exit log_tg_exit(void)
-{
-	nf_log_unregister(&ipt_log_logger);
-	xt_unregister_target(&log_tg_reg);
-}
-
-module_init(log_tg_init);
-module_exit(log_tg_exit);
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 9a68fb5..d33cddd 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -154,15 +154,6 @@ config IP6_NF_TARGET_HL
 	(e.g. when running oldconfig). It selects
 	CONFIG_NETFILTER_XT_TARGET_HL.
 
-config IP6_NF_TARGET_LOG
-	tristate "LOG target support"
-	default m if NETFILTER_ADVANCED=n
-	help
-	  This option adds a `LOG' target, which allows you to create rules in
-	  any iptables table which records the packet header to the syslog.
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
 config IP6_NF_FILTER
 	tristate "Packet filtering"
 	default m if NETFILTER_ADVANCED=n
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 2eaed96..d4dfd0a 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -31,5 +31,4 @@ obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o
 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
 
 # targets
-obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
deleted file mode 100644
index e6af8d7..0000000
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * This is a module which is used for logging packets.
- */
-
-/* (C) 2001 Jan Rekorajski <baggins@pld.org.pl>
- * (C) 2002-2004 Netfilter Core Team <coreteam@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/ip.h>
-#include <linux/spinlock.h>
-#include <linux/icmpv6.h>
-#include <net/udp.h>
-#include <net/tcp.h>
-#include <net/ipv6.h>
-#include <linux/netfilter.h>
-#include <linux/netfilter/x_tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <net/netfilter/nf_log.h>
-#include <net/netfilter/xt_log.h>
-
-MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
-MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog");
-MODULE_LICENSE("GPL");
-
-struct in_device;
-#include <net/route.h>
-#include <linux/netfilter_ipv6/ip6t_LOG.h>
-
-/* One level of recursion won't kill us */
-static void dump_packet(struct sbuff *m,
-			const struct nf_loginfo *info,
-			const struct sk_buff *skb, unsigned int ip6hoff,
-			int recurse)
-{
-	u_int8_t currenthdr;
-	int fragment;
-	struct ipv6hdr _ip6h;
-	const struct ipv6hdr *ih;
-	unsigned int ptr;
-	unsigned int hdrlen = 0;
-	unsigned int logflags;
-
-	if (info->type == NF_LOG_TYPE_LOG)
-		logflags = info->u.log.logflags;
-	else
-		logflags = NF_LOG_MASK;
-
-	ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
-	if (ih == NULL) {
-		sb_add(m, "TRUNCATED");
-		return;
-	}
-
-	/* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
-	sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
-
-	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
-	sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
-	       ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
-	       (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
-	       ih->hop_limit,
-	       (ntohl(*(__be32 *)ih) & 0x000fffff));
-
-	fragment = 0;
-	ptr = ip6hoff + sizeof(struct ipv6hdr);
-	currenthdr = ih->nexthdr;
-	while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
-		struct ipv6_opt_hdr _hdr;
-		const struct ipv6_opt_hdr *hp;
-
-		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
-		if (hp == NULL) {
-			sb_add(m, "TRUNCATED");
-			return;
-		}
-
-		/* Max length: 48 "OPT (...) " */
-		if (logflags & IP6T_LOG_IPOPT)
-			sb_add(m, "OPT ( ");
-
-		switch (currenthdr) {
-		case IPPROTO_FRAGMENT: {
-			struct frag_hdr _fhdr;
-			const struct frag_hdr *fh;
-
-			sb_add(m, "FRAG:");
-			fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
-						&_fhdr);
-			if (fh == NULL) {
-				sb_add(m, "TRUNCATED ");
-				return;
-			}
-
-			/* Max length: 6 "65535 " */
-			sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8);
-
-			/* Max length: 11 "INCOMPLETE " */
-			if (fh->frag_off & htons(0x0001))
-				sb_add(m, "INCOMPLETE ");
-
-			sb_add(m, "ID:%08x ", ntohl(fh->identification));
-
-			if (ntohs(fh->frag_off) & 0xFFF8)
-				fragment = 1;
-
-			hdrlen = 8;
-
-			break;
-		}
-		case IPPROTO_DSTOPTS:
-		case IPPROTO_ROUTING:
-		case IPPROTO_HOPOPTS:
-			if (fragment) {
-				if (logflags & IP6T_LOG_IPOPT)
-					sb_add(m, ")");
-				return;
-			}
-			hdrlen = ipv6_optlen(hp);
-			break;
-		/* Max Length */
-		case IPPROTO_AH:
-			if (logflags & IP6T_LOG_IPOPT) {
-				struct ip_auth_hdr _ahdr;
-				const struct ip_auth_hdr *ah;
-
-				/* Max length: 3 "AH " */
-				sb_add(m, "AH ");
-
-				if (fragment) {
-					sb_add(m, ")");
-					return;
-				}
-
-				ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
-							&_ahdr);
-				if (ah == NULL) {
-					/*
-					 * Max length: 26 "INCOMPLETE [65535
-					 *  bytes] )"
-					 */
-					sb_add(m, "INCOMPLETE [%u bytes] )",
-					       skb->len - ptr);
-					return;
-				}
-
-				/* Length: 15 "SPI=0xF1234567 */
-				sb_add(m, "SPI=0x%x ", ntohl(ah->spi));
-
-			}
-
-			hdrlen = (hp->hdrlen+2)<<2;
-			break;
-		case IPPROTO_ESP:
-			if (logflags & IP6T_LOG_IPOPT) {
-				struct ip_esp_hdr _esph;
-				const struct ip_esp_hdr *eh;
-
-				/* Max length: 4 "ESP " */
-				sb_add(m, "ESP ");
-
-				if (fragment) {
-					sb_add(m, ")");
-					return;
-				}
-
-				/*
-				 * Max length: 26 "INCOMPLETE [65535 bytes] )"
-				 */
-				eh = skb_header_pointer(skb, ptr, sizeof(_esph),
-							&_esph);
-				if (eh == NULL) {
-					sb_add(m, "INCOMPLETE [%u bytes] )",
-					       skb->len - ptr);
-					return;
-				}
-
-				/* Length: 16 "SPI=0xF1234567 )" */
-				sb_add(m, "SPI=0x%x )", ntohl(eh->spi) );
-
-			}
-			return;
-		default:
-			/* Max length: 20 "Unknown Ext Hdr 255" */
-			sb_add(m, "Unknown Ext Hdr %u", currenthdr);
-			return;
-		}
-		if (logflags & IP6T_LOG_IPOPT)
-			sb_add(m, ") ");
-
-		currenthdr = hp->nexthdr;
-		ptr += hdrlen;
-	}
-
-	switch (currenthdr) {
-	case IPPROTO_TCP: {
-		struct tcphdr _tcph;
-		const struct tcphdr *th;
-
-		/* Max length: 10 "PROTO=TCP " */
-		sb_add(m, "PROTO=TCP ");
-
-		if (fragment)
-			break;
-
-		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph);
-		if (th == NULL) {
-			sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
-			return;
-		}
-
-		/* Max length: 20 "SPT=65535 DPT=65535 " */
-		sb_add(m, "SPT=%u DPT=%u ",
-		       ntohs(th->source), ntohs(th->dest));
-		/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
-		if (logflags & IP6T_LOG_TCPSEQ)
-			sb_add(m, "SEQ=%u ACK=%u ",
-			       ntohl(th->seq), ntohl(th->ack_seq));
-		/* Max length: 13 "WINDOW=65535 " */
-		sb_add(m, "WINDOW=%u ", ntohs(th->window));
-		/* Max length: 9 "RES=0x3C " */
-		sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
-		/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
-		if (th->cwr)
-			sb_add(m, "CWR ");
-		if (th->ece)
-			sb_add(m, "ECE ");
-		if (th->urg)
-			sb_add(m, "URG ");
-		if (th->ack)
-			sb_add(m, "ACK ");
-		if (th->psh)
-			sb_add(m, "PSH ");
-		if (th->rst)
-			sb_add(m, "RST ");
-		if (th->syn)
-			sb_add(m, "SYN ");
-		if (th->fin)
-			sb_add(m, "FIN ");
-		/* Max length: 11 "URGP=65535 " */
-		sb_add(m, "URGP=%u ", ntohs(th->urg_ptr));
-
-		if ((logflags & IP6T_LOG_TCPOPT) &&
-		    th->doff * 4 > sizeof(struct tcphdr)) {
-			u_int8_t _opt[60 - sizeof(struct tcphdr)];
-			const u_int8_t *op;
-			unsigned int i;
-			unsigned int optsize = th->doff * 4
-					       - sizeof(struct tcphdr);
-
-			op = skb_header_pointer(skb,
-						ptr + sizeof(struct tcphdr),
-						optsize, _opt);
-			if (op == NULL) {
-				sb_add(m, "OPT (TRUNCATED)");
-				return;
-			}
-
-			/* Max length: 127 "OPT (" 15*4*2chars ") " */
-			sb_add(m, "OPT (");
-			for (i =0; i < optsize; i++)
-				sb_add(m, "%02X", op[i]);
-			sb_add(m, ") ");
-		}
-		break;
-	}
-	case IPPROTO_UDP:
-	case IPPROTO_UDPLITE: {
-		struct udphdr _udph;
-		const struct udphdr *uh;
-
-		if (currenthdr == IPPROTO_UDP)
-			/* Max length: 10 "PROTO=UDP "     */
-			sb_add(m, "PROTO=UDP " );
-		else	/* Max length: 14 "PROTO=UDPLITE " */
-			sb_add(m, "PROTO=UDPLITE ");
-
-		if (fragment)
-			break;
-
-		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph);
-		if (uh == NULL) {
-			sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
-			return;
-		}
-
-		/* Max length: 20 "SPT=65535 DPT=65535 " */
-		sb_add(m, "SPT=%u DPT=%u LEN=%u ",
-		       ntohs(uh->source), ntohs(uh->dest),
-		       ntohs(uh->len));
-		break;
-	}
-	case IPPROTO_ICMPV6: {
-		struct icmp6hdr _icmp6h;
-		const struct icmp6hdr *ic;
-
-		/* Max length: 13 "PROTO=ICMPv6 " */
-		sb_add(m, "PROTO=ICMPv6 ");
-
-		if (fragment)
-			break;
-
-		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
-		if (ic == NULL) {
-			sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
-			return;
-		}
-
-		/* Max length: 18 "TYPE=255 CODE=255 " */
-		sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code);
-
-		switch (ic->icmp6_type) {
-		case ICMPV6_ECHO_REQUEST:
-		case ICMPV6_ECHO_REPLY:
-			/* Max length: 19 "ID=65535 SEQ=65535 " */
-			sb_add(m, "ID=%u SEQ=%u ",
-				ntohs(ic->icmp6_identifier),
-				ntohs(ic->icmp6_sequence));
-			break;
-		case ICMPV6_MGM_QUERY:
-		case ICMPV6_MGM_REPORT:
-		case ICMPV6_MGM_REDUCTION:
-			break;
-
-		case ICMPV6_PARAMPROB:
-			/* Max length: 17 "POINTER=ffffffff " */
-			sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer));
-			/* Fall through */
-		case ICMPV6_DEST_UNREACH:
-		case ICMPV6_PKT_TOOBIG:
-		case ICMPV6_TIME_EXCEED:
-			/* Max length: 3+maxlen */
-			if (recurse) {
-				sb_add(m, "[");
-				dump_packet(m, info, skb,
-					    ptr + sizeof(_icmp6h), 0);
-				sb_add(m, "] ");
-			}
-
-			/* Max length: 10 "MTU=65535 " */
-			if (ic->icmp6_type == ICMPV6_PKT_TOOBIG)
-				sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu));
-		}
-		break;
-	}
-	/* Max length: 10 "PROTO=255 " */
-	default:
-		sb_add(m, "PROTO=%u ", currenthdr);
-	}
-
-	/* Max length: 15 "UID=4294967295 " */
-	if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) {
-		read_lock_bh(&skb->sk->sk_callback_lock);
-		if (skb->sk->sk_socket && skb->sk->sk_socket->file)
-			sb_add(m, "UID=%u GID=%u ",
-				skb->sk->sk_socket->file->f_cred->fsuid,
-				skb->sk->sk_socket->file->f_cred->fsgid);
-		read_unlock_bh(&skb->sk->sk_callback_lock);
-	}
-
-	/* Max length: 16 "MARK=0xFFFFFFFF " */
-	if (!recurse && skb->mark)
-		sb_add(m, "MARK=0x%x ", skb->mark);
-}
-
-static void dump_mac_header(struct sbuff *m,
-			    const struct nf_loginfo *info,
-			    const struct sk_buff *skb)
-{
-	struct net_device *dev = skb->dev;
-	unsigned int logflags = 0;
-
-	if (info->type == NF_LOG_TYPE_LOG)
-		logflags = info->u.log.logflags;
-
-	if (!(logflags & IP6T_LOG_MACDECODE))
-		goto fallback;
-
-	switch (dev->type) {
-	case ARPHRD_ETHER:
-		sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
-		       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
-		       ntohs(eth_hdr(skb)->h_proto));
-		return;
-	default:
-		break;
-	}
-
-fallback:
-	sb_add(m, "MAC=");
-	if (dev->hard_header_len &&
-	    skb->mac_header != skb->network_header) {
-		const unsigned char *p = skb_mac_header(skb);
-		unsigned int len = dev->hard_header_len;
-		unsigned int i;
-
-		if (dev->type == ARPHRD_SIT &&
-		    (p -= ETH_HLEN) < skb->head)
-			p = NULL;
-
-		if (p != NULL) {
-			sb_add(m, "%02x", *p++);
-			for (i = 1; i < len; i++)
-				sb_add(m, ":%02x", *p++);
-		}
-		sb_add(m, " ");
-
-		if (dev->type == ARPHRD_SIT) {
-			const struct iphdr *iph =
-				(struct iphdr *)skb_mac_header(skb);
-			sb_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr);
-		}
-	} else
-		sb_add(m, " ");
-}
-
-static struct nf_loginfo default_loginfo = {
-	.type	= NF_LOG_TYPE_LOG,
-	.u = {
-		.log = {
-			.level	  = 5,
-			.logflags = NF_LOG_MASK,
-		},
-	},
-};
-
-static void
-ip6t_log_packet(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 *loginfo,
-		const char *prefix)
-{
-	struct sbuff *m = sb_open();
-
-	if (!loginfo)
-		loginfo = &default_loginfo;
-
-	sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
-	       prefix,
-	       in ? in->name : "",
-	       out ? out->name : "");
-
-	if (in != NULL)
-		dump_mac_header(m, loginfo, skb);
-
-	dump_packet(m, loginfo, skb, skb_network_offset(skb), 1);
-
-	sb_close(m);
-}
-
-static unsigned int
-log_tg6(struct sk_buff *skb, const struct xt_action_param *par)
-{
-	const struct ip6t_log_info *loginfo = par->targinfo;
-	struct nf_loginfo li;
-
-	li.type = NF_LOG_TYPE_LOG;
-	li.u.log.level = loginfo->level;
-	li.u.log.logflags = loginfo->logflags;
-
-	ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, par->out,
-			&li, loginfo->prefix);
-	return XT_CONTINUE;
-}
-
-
-static int log_tg6_check(const struct xt_tgchk_param *par)
-{
-	const struct ip6t_log_info *loginfo = par->targinfo;
-
-	if (loginfo->level >= 8) {
-		pr_debug("level %u >= 8\n", loginfo->level);
-		return -EINVAL;
-	}
-	if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
-		pr_debug("prefix not null-terminated\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static struct xt_target log_tg6_reg __read_mostly = {
-	.name 		= "LOG",
-	.family		= NFPROTO_IPV6,
-	.target 	= log_tg6,
-	.targetsize	= sizeof(struct ip6t_log_info),
-	.checkentry	= log_tg6_check,
-	.me 		= THIS_MODULE,
-};
-
-static struct nf_logger ip6t_logger __read_mostly = {
-	.name		= "ip6t_LOG",
-	.logfn		= &ip6t_log_packet,
-	.me		= THIS_MODULE,
-};
-
-static int __init log_tg6_init(void)
-{
-	int ret;
-
-	ret = xt_register_target(&log_tg6_reg);
-	if (ret < 0)
-		return ret;
-	nf_log_register(NFPROTO_IPV6, &ip6t_logger);
-	return 0;
-}
-
-static void __exit log_tg6_exit(void)
-{
-	nf_log_unregister(&ip6t_logger);
-	xt_unregister_target(&log_tg6_reg);
-}
-
-module_init(log_tg6_init);
-module_exit(log_tg6_exit);
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index f8ac4ef..b895d8b 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -524,6 +524,15 @@ config NETFILTER_XT_TARGET_LED
 	  For more information on the LEDs available on your system, see
 	  Documentation/leds/leds-class.txt
 
+config NETFILTER_XT_TARGET_LOG
+	tristate "LOG target support"
+	default m if NETFILTER_ADVANCED=n
+	help
+	  This option adds a `LOG' target, which allows you to create rules in
+	  any iptables table which records the packet header to the syslog.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_TARGET_MARK
 	tristate '"MARK" target support'
 	depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 40f4c3d..a28c2a6 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
new file mode 100644
index 0000000..1595608
--- /dev/null
+++ b/net/netfilter/xt_LOG.c
@@ -0,0 +1,921 @@
+/*
+ * This is a module which is used for logging packets.
+ */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@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/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ip.h>
+#include <net/ipv6.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/tcp.h>
+#include <net/route.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_LOG.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <net/netfilter/nf_log.h>
+#include <net/netfilter/xt_log.h>
+
+static struct nf_loginfo default_loginfo = {
+	.type	= NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level    = 5,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static int dump_udp_header(struct sbuff *m, const struct sk_buff *skb,
+			   u8 proto, int fragment, unsigned int offset)
+{
+	struct udphdr _udph;
+	const struct udphdr *uh;
+
+	if (proto == IPPROTO_UDP)
+		/* Max length: 10 "PROTO=UDP "     */
+		sb_add(m, "PROTO=UDP ");
+	else	/* Max length: 14 "PROTO=UDPLITE " */
+		sb_add(m, "PROTO=UDPLITE ");
+
+	if (fragment)
+		goto out;
+
+	/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+	uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
+	if (uh == NULL) {
+		sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
+
+		return 1;
+	}
+
+	/* Max length: 20 "SPT=65535 DPT=65535 " */
+	sb_add(m, "SPT=%u DPT=%u LEN=%u ", ntohs(uh->source), ntohs(uh->dest),
+		ntohs(uh->len));
+
+out:
+	return 0;
+}
+
+static int dump_tcp_header(struct sbuff *m, const struct sk_buff *skb,
+			   u8 proto, int fragment, unsigned int offset,
+			   unsigned int logflags)
+{
+	struct tcphdr _tcph;
+	const struct tcphdr *th;
+
+	/* Max length: 10 "PROTO=TCP " */
+	sb_add(m, "PROTO=TCP ");
+
+	if (fragment)
+		return 0;
+
+	/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+	th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+	if (th == NULL) {
+		sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
+		return 1;
+	}
+
+	/* Max length: 20 "SPT=65535 DPT=65535 " */
+	sb_add(m, "SPT=%u DPT=%u ", ntohs(th->source), ntohs(th->dest));
+	/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
+	if (logflags & XT_LOG_TCPSEQ)
+		sb_add(m, "SEQ=%u ACK=%u ", ntohl(th->seq), ntohl(th->ack_seq));
+
+	/* Max length: 13 "WINDOW=65535 " */
+	sb_add(m, "WINDOW=%u ", ntohs(th->window));
+	/* Max length: 9 "RES=0x3C " */
+	sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) &
+					    TCP_RESERVED_BITS) >> 22));
+	/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
+	if (th->cwr)
+		sb_add(m, "CWR ");
+	if (th->ece)
+		sb_add(m, "ECE ");
+	if (th->urg)
+		sb_add(m, "URG ");
+	if (th->ack)
+		sb_add(m, "ACK ");
+	if (th->psh)
+		sb_add(m, "PSH ");
+	if (th->rst)
+		sb_add(m, "RST ");
+	if (th->syn)
+		sb_add(m, "SYN ");
+	if (th->fin)
+		sb_add(m, "FIN ");
+	/* Max length: 11 "URGP=65535 " */
+	sb_add(m, "URGP=%u ", ntohs(th->urg_ptr));
+
+	if ((logflags & XT_LOG_TCPOPT) && th->doff*4 > sizeof(struct tcphdr)) {
+		u_int8_t _opt[60 - sizeof(struct tcphdr)];
+		const u_int8_t *op;
+		unsigned int i;
+		unsigned int optsize = th->doff*4 - sizeof(struct tcphdr);
+
+		op = skb_header_pointer(skb, offset + sizeof(struct tcphdr),
+					optsize, _opt);
+		if (op == NULL) {
+			sb_add(m, "OPT (TRUNCATED)");
+			return 1;
+		}
+
+		/* Max length: 127 "OPT (" 15*4*2chars ") " */
+		sb_add(m, "OPT (");
+		for (i = 0; i < optsize; i++)
+			sb_add(m, "%02X", op[i]);
+
+		sb_add(m, ") ");
+	}
+
+	return 0;
+}
+
+/* One level of recursion won't kill us */
+static void dump_ipv4_packet(struct sbuff *m,
+			const struct nf_loginfo *info,
+			const struct sk_buff *skb,
+			unsigned int iphoff)
+{
+	struct iphdr _iph;
+	const struct iphdr *ih;
+	unsigned int logflags;
+
+	if (info->type == NF_LOG_TYPE_LOG)
+		logflags = info->u.log.logflags;
+	else
+		logflags = NF_LOG_MASK;
+
+	ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
+	if (ih == NULL) {
+		sb_add(m, "TRUNCATED");
+		return;
+	}
+
+	/* Important fields:
+	 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
+	/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
+	sb_add(m, "SRC=%pI4 DST=%pI4 ",
+	       &ih->saddr, &ih->daddr);
+
+	/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
+	sb_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
+	       ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
+	       ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
+
+	/* Max length: 6 "CE DF MF " */
+	if (ntohs(ih->frag_off) & IP_CE)
+		sb_add(m, "CE ");
+	if (ntohs(ih->frag_off) & IP_DF)
+		sb_add(m, "DF ");
+	if (ntohs(ih->frag_off) & IP_MF)
+		sb_add(m, "MF ");
+
+	/* Max length: 11 "FRAG:65535 " */
+	if (ntohs(ih->frag_off) & IP_OFFSET)
+		sb_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
+
+	if ((logflags & XT_LOG_IPOPT) &&
+	    ih->ihl * 4 > sizeof(struct iphdr)) {
+		const unsigned char *op;
+		unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
+		unsigned int i, optsize;
+
+		optsize = ih->ihl * 4 - sizeof(struct iphdr);
+		op = skb_header_pointer(skb, iphoff+sizeof(_iph),
+					optsize, _opt);
+		if (op == NULL) {
+			sb_add(m, "TRUNCATED");
+			return;
+		}
+
+		/* Max length: 127 "OPT (" 15*4*2chars ") " */
+		sb_add(m, "OPT (");
+		for (i = 0; i < optsize; i++)
+			sb_add(m, "%02X", op[i]);
+		sb_add(m, ") ");
+	}
+
+	switch (ih->protocol) {
+	case IPPROTO_TCP:
+		if (dump_tcp_header(m, skb, ih->protocol,
+				    ntohs(ih->frag_off) & IP_OFFSET,
+				    iphoff+ih->ihl*4, logflags))
+			return;
+	case IPPROTO_UDP:
+	case IPPROTO_UDPLITE:
+		if (dump_udp_header(m, skb, ih->protocol,
+				    ntohs(ih->frag_off) & IP_OFFSET,
+				    iphoff+ih->ihl*4))
+			return;
+	case IPPROTO_ICMP: {
+		struct icmphdr _icmph;
+		const struct icmphdr *ich;
+		static const size_t required_len[NR_ICMP_TYPES+1]
+			= { [ICMP_ECHOREPLY] = 4,
+			    [ICMP_DEST_UNREACH]
+			    = 8 + sizeof(struct iphdr),
+			    [ICMP_SOURCE_QUENCH]
+			    = 8 + sizeof(struct iphdr),
+			    [ICMP_REDIRECT]
+			    = 8 + sizeof(struct iphdr),
+			    [ICMP_ECHO] = 4,
+			    [ICMP_TIME_EXCEEDED]
+			    = 8 + sizeof(struct iphdr),
+			    [ICMP_PARAMETERPROB]
+			    = 8 + sizeof(struct iphdr),
+			    [ICMP_TIMESTAMP] = 20,
+			    [ICMP_TIMESTAMPREPLY] = 20,
+			    [ICMP_ADDRESS] = 12,
+			    [ICMP_ADDRESSREPLY] = 12 };
+
+		/* Max length: 11 "PROTO=ICMP " */
+		sb_add(m, "PROTO=ICMP ");
+
+		if (ntohs(ih->frag_off) & IP_OFFSET)
+			break;
+
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
+					 sizeof(_icmph), &_icmph);
+		if (ich == NULL) {
+			sb_add(m, "INCOMPLETE [%u bytes] ",
+			       skb->len - iphoff - ih->ihl*4);
+			break;
+		}
+
+		/* Max length: 18 "TYPE=255 CODE=255 " */
+		sb_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code);
+
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		if (ich->type <= NR_ICMP_TYPES &&
+		    required_len[ich->type] &&
+		    skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
+			sb_add(m, "INCOMPLETE [%u bytes] ",
+			       skb->len - iphoff - ih->ihl*4);
+			break;
+		}
+
+		switch (ich->type) {
+		case ICMP_ECHOREPLY:
+		case ICMP_ECHO:
+			/* Max length: 19 "ID=65535 SEQ=65535 " */
+			sb_add(m, "ID=%u SEQ=%u ",
+			       ntohs(ich->un.echo.id),
+			       ntohs(ich->un.echo.sequence));
+			break;
+
+		case ICMP_PARAMETERPROB:
+			/* Max length: 14 "PARAMETER=255 " */
+			sb_add(m, "PARAMETER=%u ",
+			       ntohl(ich->un.gateway) >> 24);
+			break;
+		case ICMP_REDIRECT:
+			/* Max length: 24 "GATEWAY=255.255.255.255 " */
+			sb_add(m, "GATEWAY=%pI4 ", &ich->un.gateway);
+			/* Fall through */
+		case ICMP_DEST_UNREACH:
+		case ICMP_SOURCE_QUENCH:
+		case ICMP_TIME_EXCEEDED:
+			/* Max length: 3+maxlen */
+			if (!iphoff) { /* Only recurse once. */
+				sb_add(m, "[");
+				dump_ipv4_packet(m, info, skb,
+					    iphoff + ih->ihl*4+sizeof(_icmph));
+				sb_add(m, "] ");
+			}
+
+			/* Max length: 10 "MTU=65535 " */
+			if (ich->type == ICMP_DEST_UNREACH &&
+			    ich->code == ICMP_FRAG_NEEDED)
+				sb_add(m, "MTU=%u ", ntohs(ich->un.frag.mtu));
+		}
+		break;
+	}
+	/* Max Length */
+	case IPPROTO_AH: {
+		struct ip_auth_hdr _ahdr;
+		const struct ip_auth_hdr *ah;
+
+		if (ntohs(ih->frag_off) & IP_OFFSET)
+			break;
+
+		/* Max length: 9 "PROTO=AH " */
+		sb_add(m, "PROTO=AH ");
+
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
+					sizeof(_ahdr), &_ahdr);
+		if (ah == NULL) {
+			sb_add(m, "INCOMPLETE [%u bytes] ",
+			       skb->len - iphoff - ih->ihl*4);
+			break;
+		}
+
+		/* Length: 15 "SPI=0xF1234567 " */
+		sb_add(m, "SPI=0x%x ", ntohl(ah->spi));
+		break;
+	}
+	case IPPROTO_ESP: {
+		struct ip_esp_hdr _esph;
+		const struct ip_esp_hdr *eh;
+
+		/* Max length: 10 "PROTO=ESP " */
+		sb_add(m, "PROTO=ESP ");
+
+		if (ntohs(ih->frag_off) & IP_OFFSET)
+			break;
+
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
+					sizeof(_esph), &_esph);
+		if (eh == NULL) {
+			sb_add(m, "INCOMPLETE [%u bytes] ",
+			       skb->len - iphoff - ih->ihl*4);
+			break;
+		}
+
+		/* Length: 15 "SPI=0xF1234567 " */
+		sb_add(m, "SPI=0x%x ", ntohl(eh->spi));
+		break;
+	}
+	/* Max length: 10 "PROTO 255 " */
+	default:
+		sb_add(m, "PROTO=%u ", ih->protocol);
+	}
+
+	/* Max length: 15 "UID=4294967295 " */
+	if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) {
+		read_lock_bh(&skb->sk->sk_callback_lock);
+		if (skb->sk->sk_socket && skb->sk->sk_socket->file)
+			sb_add(m, "UID=%u GID=%u ",
+				skb->sk->sk_socket->file->f_cred->fsuid,
+				skb->sk->sk_socket->file->f_cred->fsgid);
+		read_unlock_bh(&skb->sk->sk_callback_lock);
+	}
+
+	/* Max length: 16 "MARK=0xFFFFFFFF " */
+	if (!iphoff && skb->mark)
+		sb_add(m, "MARK=0x%x ", skb->mark);
+
+	/* Proto    Max log string length */
+	/* IP:      40+46+6+11+127 = 230 */
+	/* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
+	/* UDP:     10+max(25,20) = 35 */
+	/* UDPLITE: 14+max(25,20) = 39 */
+	/* ICMP:    11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
+	/* ESP:     10+max(25)+15 = 50 */
+	/* AH:      9+max(25)+15 = 49 */
+	/* unknown: 10 */
+
+	/* (ICMP allows recursion one level deep) */
+	/* maxlen =  IP + ICMP +  IP + max(TCP,UDP,ICMP,unknown) */
+	/* maxlen = 230+   91  + 230 + 252 = 803 */
+}
+
+static void dump_ipv4_mac_header(struct sbuff *m,
+			    const struct nf_loginfo *info,
+			    const struct sk_buff *skb)
+{
+	struct net_device *dev = skb->dev;
+	unsigned int logflags = 0;
+
+	if (info->type == NF_LOG_TYPE_LOG)
+		logflags = info->u.log.logflags;
+
+	if (!(logflags & XT_LOG_MACDECODE))
+		goto fallback;
+
+	switch (dev->type) {
+	case ARPHRD_ETHER:
+		sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
+		       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
+		       ntohs(eth_hdr(skb)->h_proto));
+		return;
+	default:
+		break;
+	}
+
+fallback:
+	sb_add(m, "MAC=");
+	if (dev->hard_header_len &&
+	    skb->mac_header != skb->network_header) {
+		const unsigned char *p = skb_mac_header(skb);
+		unsigned int i;
+
+		sb_add(m, "%02x", *p++);
+		for (i = 1; i < dev->hard_header_len; i++, p++)
+			sb_add(m, ":%02x", *p);
+	}
+	sb_add(m, " ");
+}
+
+static void
+log_packet_common(struct sbuff *m,
+		  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 *loginfo,
+		  const char *prefix)
+{
+	sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
+	       prefix,
+	       in ? in->name : "",
+	       out ? out->name : "");
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge) {
+		const struct net_device *physindev;
+		const struct net_device *physoutdev;
+
+		physindev = skb->nf_bridge->physindev;
+		if (physindev && in != physindev)
+			sb_add(m, "PHYSIN=%s ", physindev->name);
+		physoutdev = skb->nf_bridge->physoutdev;
+		if (physoutdev && out != physoutdev)
+			sb_add(m, "PHYSOUT=%s ", physoutdev->name);
+	}
+#endif
+}
+
+
+static void
+ipt_log_packet(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 *loginfo,
+	       const char *prefix)
+{
+	struct sbuff *m = sb_open();
+
+	if (!loginfo)
+		loginfo = &default_loginfo;
+
+	log_packet_common(m, pf, hooknum, skb, in, out, loginfo, prefix);
+
+	if (in != NULL)
+		dump_ipv4_mac_header(m, loginfo, skb);
+
+	dump_ipv4_packet(m, loginfo, skb, 0);
+
+	sb_close(m);
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+/* One level of recursion won't kill us */
+static void dump_ipv6_packet(struct sbuff *m,
+			const struct nf_loginfo *info,
+			const struct sk_buff *skb, unsigned int ip6hoff,
+			int recurse)
+{
+	u_int8_t currenthdr;
+	int fragment;
+	struct ipv6hdr _ip6h;
+	const struct ipv6hdr *ih;
+	unsigned int ptr;
+	unsigned int hdrlen = 0;
+	unsigned int logflags;
+
+	if (info->type == NF_LOG_TYPE_LOG)
+		logflags = info->u.log.logflags;
+	else
+		logflags = NF_LOG_MASK;
+
+	ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
+	if (ih == NULL) {
+		sb_add(m, "TRUNCATED");
+		return;
+	}
+
+	/* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
+	sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
+
+	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
+	sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
+	       ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
+	       (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
+	       ih->hop_limit,
+	       (ntohl(*(__be32 *)ih) & 0x000fffff));
+
+	fragment = 0;
+	ptr = ip6hoff + sizeof(struct ipv6hdr);
+	currenthdr = ih->nexthdr;
+	while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
+		struct ipv6_opt_hdr _hdr;
+		const struct ipv6_opt_hdr *hp;
+
+		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+		if (hp == NULL) {
+			sb_add(m, "TRUNCATED");
+			return;
+		}
+
+		/* Max length: 48 "OPT (...) " */
+		if (logflags & XT_LOG_IPOPT)
+			sb_add(m, "OPT ( ");
+
+		switch (currenthdr) {
+		case IPPROTO_FRAGMENT: {
+			struct frag_hdr _fhdr;
+			const struct frag_hdr *fh;
+
+			sb_add(m, "FRAG:");
+			fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
+						&_fhdr);
+			if (fh == NULL) {
+				sb_add(m, "TRUNCATED ");
+				return;
+			}
+
+			/* Max length: 6 "65535 " */
+			sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8);
+
+			/* Max length: 11 "INCOMPLETE " */
+			if (fh->frag_off & htons(0x0001))
+				sb_add(m, "INCOMPLETE ");
+
+			sb_add(m, "ID:%08x ", ntohl(fh->identification));
+
+			if (ntohs(fh->frag_off) & 0xFFF8)
+				fragment = 1;
+
+			hdrlen = 8;
+
+			break;
+		}
+		case IPPROTO_DSTOPTS:
+		case IPPROTO_ROUTING:
+		case IPPROTO_HOPOPTS:
+			if (fragment) {
+				if (logflags & XT_LOG_IPOPT)
+					sb_add(m, ")");
+				return;
+			}
+			hdrlen = ipv6_optlen(hp);
+			break;
+		/* Max Length */
+		case IPPROTO_AH:
+			if (logflags & XT_LOG_IPOPT) {
+				struct ip_auth_hdr _ahdr;
+				const struct ip_auth_hdr *ah;
+
+				/* Max length: 3 "AH " */
+				sb_add(m, "AH ");
+
+				if (fragment) {
+					sb_add(m, ")");
+					return;
+				}
+
+				ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
+							&_ahdr);
+				if (ah == NULL) {
+					/*
+					 * Max length: 26 "INCOMPLETE [65535
+					 *  bytes] )"
+					 */
+					sb_add(m, "INCOMPLETE [%u bytes] )",
+					       skb->len - ptr);
+					return;
+				}
+
+				/* Length: 15 "SPI=0xF1234567 */
+				sb_add(m, "SPI=0x%x ", ntohl(ah->spi));
+
+			}
+
+			hdrlen = (hp->hdrlen+2)<<2;
+			break;
+		case IPPROTO_ESP:
+			if (logflags & XT_LOG_IPOPT) {
+				struct ip_esp_hdr _esph;
+				const struct ip_esp_hdr *eh;
+
+				/* Max length: 4 "ESP " */
+				sb_add(m, "ESP ");
+
+				if (fragment) {
+					sb_add(m, ")");
+					return;
+				}
+
+				/*
+				 * Max length: 26 "INCOMPLETE [65535 bytes] )"
+				 */
+				eh = skb_header_pointer(skb, ptr, sizeof(_esph),
+							&_esph);
+				if (eh == NULL) {
+					sb_add(m, "INCOMPLETE [%u bytes] )",
+					       skb->len - ptr);
+					return;
+				}
+
+				/* Length: 16 "SPI=0xF1234567 )" */
+				sb_add(m, "SPI=0x%x )", ntohl(eh->spi));
+
+			}
+			return;
+		default:
+			/* Max length: 20 "Unknown Ext Hdr 255" */
+			sb_add(m, "Unknown Ext Hdr %u", currenthdr);
+			return;
+		}
+		if (logflags & XT_LOG_IPOPT)
+			sb_add(m, ") ");
+
+		currenthdr = hp->nexthdr;
+		ptr += hdrlen;
+	}
+
+	switch (currenthdr) {
+	case IPPROTO_TCP:
+		if (dump_tcp_header(m, skb, currenthdr, fragment, ptr,
+		    logflags))
+			return;
+	case IPPROTO_UDP:
+	case IPPROTO_UDPLITE:
+		if (dump_udp_header(m, skb, currenthdr, fragment, ptr))
+			return;
+	case IPPROTO_ICMPV6: {
+		struct icmp6hdr _icmp6h;
+		const struct icmp6hdr *ic;
+
+		/* Max length: 13 "PROTO=ICMPv6 " */
+		sb_add(m, "PROTO=ICMPv6 ");
+
+		if (fragment)
+			break;
+
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
+		if (ic == NULL) {
+			sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
+			return;
+		}
+
+		/* Max length: 18 "TYPE=255 CODE=255 " */
+		sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code);
+
+		switch (ic->icmp6_type) {
+		case ICMPV6_ECHO_REQUEST:
+		case ICMPV6_ECHO_REPLY:
+			/* Max length: 19 "ID=65535 SEQ=65535 " */
+			sb_add(m, "ID=%u SEQ=%u ",
+				ntohs(ic->icmp6_identifier),
+				ntohs(ic->icmp6_sequence));
+			break;
+		case ICMPV6_MGM_QUERY:
+		case ICMPV6_MGM_REPORT:
+		case ICMPV6_MGM_REDUCTION:
+			break;
+
+		case ICMPV6_PARAMPROB:
+			/* Max length: 17 "POINTER=ffffffff " */
+			sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer));
+			/* Fall through */
+		case ICMPV6_DEST_UNREACH:
+		case ICMPV6_PKT_TOOBIG:
+		case ICMPV6_TIME_EXCEED:
+			/* Max length: 3+maxlen */
+			if (recurse) {
+				sb_add(m, "[");
+				dump_ipv6_packet(m, info, skb,
+					    ptr + sizeof(_icmp6h), 0);
+				sb_add(m, "] ");
+			}
+
+			/* Max length: 10 "MTU=65535 " */
+			if (ic->icmp6_type == ICMPV6_PKT_TOOBIG)
+				sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu));
+		}
+		break;
+	}
+	/* Max length: 10 "PROTO=255 " */
+	default:
+		sb_add(m, "PROTO=%u ", currenthdr);
+	}
+
+	/* Max length: 15 "UID=4294967295 " */
+	if ((logflags & XT_LOG_UID) && recurse && skb->sk) {
+		read_lock_bh(&skb->sk->sk_callback_lock);
+		if (skb->sk->sk_socket && skb->sk->sk_socket->file)
+			sb_add(m, "UID=%u GID=%u ",
+				skb->sk->sk_socket->file->f_cred->fsuid,
+				skb->sk->sk_socket->file->f_cred->fsgid);
+		read_unlock_bh(&skb->sk->sk_callback_lock);
+	}
+
+	/* Max length: 16 "MARK=0xFFFFFFFF " */
+	if (!recurse && skb->mark)
+		sb_add(m, "MARK=0x%x ", skb->mark);
+}
+
+static void dump_ipv6_mac_header(struct sbuff *m,
+			    const struct nf_loginfo *info,
+			    const struct sk_buff *skb)
+{
+	struct net_device *dev = skb->dev;
+	unsigned int logflags = 0;
+
+	if (info->type == NF_LOG_TYPE_LOG)
+		logflags = info->u.log.logflags;
+
+	if (!(logflags & XT_LOG_MACDECODE))
+		goto fallback;
+
+	switch (dev->type) {
+	case ARPHRD_ETHER:
+		sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
+		       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
+		       ntohs(eth_hdr(skb)->h_proto));
+		return;
+	default:
+		break;
+	}
+
+fallback:
+	sb_add(m, "MAC=");
+	if (dev->hard_header_len &&
+	    skb->mac_header != skb->network_header) {
+		const unsigned char *p = skb_mac_header(skb);
+		unsigned int len = dev->hard_header_len;
+		unsigned int i;
+
+		if (dev->type == ARPHRD_SIT) {
+			p -= ETH_HLEN;
+
+			if (p < skb->head)
+				p = NULL;
+		}
+
+		if (p != NULL) {
+			sb_add(m, "%02x", *p++);
+			for (i = 1; i < len; i++)
+				sb_add(m, ":%02x", *p++);
+		}
+		sb_add(m, " ");
+
+		if (dev->type == ARPHRD_SIT) {
+			const struct iphdr *iph =
+				(struct iphdr *)skb_mac_header(skb);
+			sb_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr,
+			       &iph->daddr);
+		}
+	} else
+		sb_add(m, " ");
+}
+
+static void
+ip6t_log_packet(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 *loginfo,
+		const char *prefix)
+{
+	struct sbuff *m = sb_open();
+
+	if (!loginfo)
+		loginfo = &default_loginfo;
+
+	log_packet_common(m, pf, hooknum, skb, in, out, loginfo, prefix);
+
+	if (in != NULL)
+		dump_ipv6_mac_header(m, loginfo, skb);
+
+	dump_ipv6_packet(m, loginfo, skb, skb_network_offset(skb), 1);
+
+	sb_close(m);
+}
+#endif
+
+static unsigned int
+log_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_log_info *loginfo = par->targinfo;
+	struct nf_loginfo li;
+
+	li.type = NF_LOG_TYPE_LOG;
+	li.u.log.level = loginfo->level;
+	li.u.log.logflags = loginfo->logflags;
+
+	if (par->family == NFPROTO_IPV4)
+		ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in,
+			       par->out, &li, loginfo->prefix);
+#if IS_ENABLED(CONFIG_IPV6)
+	else if (par->family == NFPROTO_IPV6)
+		ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in,
+				par->out, &li, loginfo->prefix);
+#endif
+	else
+		WARN_ON_ONCE(1);
+
+	return XT_CONTINUE;
+}
+
+static int log_tg_check(const struct xt_tgchk_param *par)
+{
+	const struct xt_log_info *loginfo = par->targinfo;
+
+	if (par->family != NFPROTO_IPV4 && par->family != NFPROTO_IPV6)
+		return -EINVAL;
+
+	if (loginfo->level >= 8) {
+		pr_debug("level %u >= 8\n", loginfo->level);
+		return -EINVAL;
+	}
+
+	if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
+		pr_debug("prefix is not null-terminated\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct xt_target log_tg_regs[] __read_mostly = {
+	{
+		.name		= "LOG",
+		.family		= NFPROTO_IPV4,
+		.target		= log_tg,
+		.targetsize	= sizeof(struct xt_log_info),
+		.checkentry	= log_tg_check,
+		.me		= THIS_MODULE,
+	},
+#if IS_ENABLED(CONFIG_IPV6)
+	{
+		.name		= "LOG",
+		.family		= NFPROTO_IPV6,
+		.target		= log_tg,
+		.targetsize	= sizeof(struct xt_log_info),
+		.checkentry	= log_tg_check,
+		.me		= THIS_MODULE,
+	},
+#endif
+};
+
+static struct nf_logger ipt_log_logger __read_mostly = {
+	.name		= "ipt_LOG",
+	.logfn		= &ipt_log_packet,
+	.me		= THIS_MODULE,
+};
+
+#if IS_ENABLED(CONFIG_IPV6)
+static struct nf_logger ip6t_log_logger __read_mostly = {
+	.name		= "ip6t_LOG",
+	.logfn		= &ip6t_log_packet,
+	.me		= THIS_MODULE,
+};
+#endif
+
+static int __init log_tg_init(void)
+{
+	int ret;
+
+	ret = xt_register_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs));
+	if (ret < 0)
+		return ret;
+
+	nf_log_register(NFPROTO_IPV4, &ipt_log_logger);
+#if IS_ENABLED(CONFIG_IPV6)
+	nf_log_register(NFPROTO_IPV6, &ip6t_log_logger);
+#endif
+	return 0;
+}
+
+static void __exit log_tg_exit(void)
+{
+	nf_log_unregister(&ipt_log_logger);
+#if IS_ENABLED(CONFIG_IPV6)
+	nf_log_unregister(&ip6t_log_logger);
+#endif
+	xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs));
+}
+
+module_init(log_tg_init);
+module_exit(log_tg_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
+MODULE_DESCRIPTION("Xtables: IPv4/IPv6 packet logging");
+MODULE_ALIAS("ipt_LOG");
+MODULE_ALIAS("ip6t_LOG");
-- 
1.7.7.3


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

* [PATCH 2/6] netfilter: xt_LOG: fix bogus extra layer-4 logging information
  2012-03-05 23:19 [PATCH v6] Netfilter ring buffer support Richard Weinberger
  2012-03-05 23:19 ` [PATCH 1/6] Netfilter: Merge ipt_LOG and ip6_LOG into xt_LOG Richard Weinberger
@ 2012-03-05 23:19 ` Richard Weinberger
  2012-03-05 23:19 ` [PATCH 3/6] ring_buffer: Export for_each_buffer_cpu() Richard Weinberger
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Richard Weinberger @ 2012-03-05 23:19 UTC (permalink / raw)
  To: pablo
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel,
	rostedt, Richard Weinberger

In 16059b5 netfilter: merge ipt_LOG and ip6_LOG into xt_LOG, we have
merged ipt_LOG and ip6t_LOG.

However:

IN=wlan0 OUT= MAC=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
SRC=213.150.61.61 DST=192.168.1.133 LEN=40 TOS=0x00 PREC=0x00 TTL=117
ID=10539 DF PROTO=TCP SPT=80 DPT=49013 WINDOW=0 RES=0x00 ACK RST
URGP=0 PROTO=UDPLITE SPT=80 DPT=49013 LEN=45843 PROTO=ICMP TYPE=0
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Several missing break in the code led to including bogus layer-4
information. This patch fixes this problem.

Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/xt_LOG.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
index 1595608..f99f8de 100644
--- a/net/netfilter/xt_LOG.c
+++ b/net/netfilter/xt_LOG.c
@@ -216,12 +216,14 @@ static void dump_ipv4_packet(struct sbuff *m,
 				    ntohs(ih->frag_off) & IP_OFFSET,
 				    iphoff+ih->ihl*4, logflags))
 			return;
+		break;
 	case IPPROTO_UDP:
 	case IPPROTO_UDPLITE:
 		if (dump_udp_header(m, skb, ih->protocol,
 				    ntohs(ih->frag_off) & IP_OFFSET,
 				    iphoff+ih->ihl*4))
 			return;
+		break;
 	case IPPROTO_ICMP: {
 		struct icmphdr _icmph;
 		const struct icmphdr *ich;
@@ -649,10 +651,12 @@ static void dump_ipv6_packet(struct sbuff *m,
 		if (dump_tcp_header(m, skb, currenthdr, fragment, ptr,
 		    logflags))
 			return;
+		break;
 	case IPPROTO_UDP:
 	case IPPROTO_UDPLITE:
 		if (dump_udp_header(m, skb, currenthdr, fragment, ptr))
 			return;
+		break;
 	case IPPROTO_ICMPV6: {
 		struct icmp6hdr _icmp6h;
 		const struct icmp6hdr *ic;
-- 
1.7.7.3


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

* [PATCH 3/6] ring_buffer: Export for_each_buffer_cpu()
  2012-03-05 23:19 [PATCH v6] Netfilter ring buffer support Richard Weinberger
  2012-03-05 23:19 ` [PATCH 1/6] Netfilter: Merge ipt_LOG and ip6_LOG into xt_LOG Richard Weinberger
  2012-03-05 23:19 ` [PATCH 2/6] netfilter: xt_LOG: fix bogus extra layer-4 logging information Richard Weinberger
@ 2012-03-05 23:19 ` Richard Weinberger
  2012-03-05 23:19 ` [PATCH 4/6] xt_log: Make printk() in sb_close() optional Richard Weinberger
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Richard Weinberger @ 2012-03-05 23:19 UTC (permalink / raw)
  To: pablo
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel,
	rostedt, Richard Weinberger

In order to make ring_buffer usable to other modules
for_each_buffer_cpu() needs to be exported.

Signed-off-by: Richard Weinberger <richard@nod.at>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
---
 include/linux/ring_buffer.h |    5 +++++
 kernel/trace/ring_buffer.c  |    7 +++++++
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 67be037..5c1c29f 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -185,4 +185,9 @@ enum ring_buffer_flags {
 	RB_FL_OVERWRITE		= 1 << 0,
 };
 
+cpumask_var_t *ring_buffer_mask(struct ring_buffer *buffer);
+
+#define for_each_buffer_cpu(buffer, cpu) \
+	for_each_cpu(cpu, *(ring_buffer_mask(buffer)))
+
 #endif /* _LINUX_RING_BUFFER_H */
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index f5b7b5c..a4117c5 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -348,6 +348,7 @@ void *ring_buffer_event_data(struct ring_buffer_event *event)
 }
 EXPORT_SYMBOL_GPL(ring_buffer_event_data);
 
+#undef for_each_buffer_cpu
 #define for_each_buffer_cpu(buffer, cpu)		\
 	for_each_cpu(cpu, buffer->cpumask)
 
@@ -4139,3 +4140,9 @@ static int rb_cpu_notify(struct notifier_block *self,
 	return NOTIFY_OK;
 }
 #endif
+
+cpumask_var_t *ring_buffer_mask(struct ring_buffer *buffer)
+{
+	return &buffer->cpumask;
+}
+EXPORT_SYMBOL_GPL(ring_buffer_mask);
-- 
1.7.7.3


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

* [PATCH 4/6] xt_log: Make printk() in sb_close() optional
  2012-03-05 23:19 [PATCH v6] Netfilter ring buffer support Richard Weinberger
                   ` (2 preceding siblings ...)
  2012-03-05 23:19 ` [PATCH 3/6] ring_buffer: Export for_each_buffer_cpu() Richard Weinberger
@ 2012-03-05 23:19 ` Richard Weinberger
  2012-03-05 23:19 ` [PATCH 5/6] Netfilter: xt_LOG: Implement ring buffer support Richard Weinberger
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Richard Weinberger @ 2012-03-05 23:19 UTC (permalink / raw)
  To: pablo
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel,
	rostedt, Richard Weinberger

Make printk() in sb_close() optional such that other modules
can build a log string without printing it using printk().

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/net/netfilter/xt_log.h |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/include/net/netfilter/xt_log.h b/include/net/netfilter/xt_log.h
index 0dfb34a..767e08d 100644
--- a/include/net/netfilter/xt_log.h
+++ b/include/net/netfilter/xt_log.h
@@ -39,10 +39,12 @@ static struct sbuff *sb_open(void)
 	return m;
 }
 
-static void sb_close(struct sbuff *m)
+static void __sb_close(struct sbuff *m, int print)
 {
-	m->buf[m->count] = 0;
-	printk("%s\n", m->buf);
+	if (print) {
+		m->buf[m->count] = 0;
+		printk("%s\n", m->buf);
+	}
 
 	if (likely(m != &emergency))
 		kfree(m);
@@ -52,3 +54,4 @@ static void sb_close(struct sbuff *m)
 	}
 }
 
+#define sb_close(m)	__sb_close(m, 1)
-- 
1.7.7.3


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

* [PATCH 5/6] Netfilter: xt_LOG: Implement ring buffer support
  2012-03-05 23:19 [PATCH v6] Netfilter ring buffer support Richard Weinberger
                   ` (3 preceding siblings ...)
  2012-03-05 23:19 ` [PATCH 4/6] xt_log: Make printk() in sb_close() optional Richard Weinberger
@ 2012-03-05 23:19 ` Richard Weinberger
  2012-03-06  2:47   ` Steven Rostedt
  2012-03-05 23:19 ` [PATCH 6/6] Netfilter: xt_LOG: Add timestamp support Richard Weinberger
  2012-03-08  1:28 ` [PATCH v6] Netfilter ring buffer support Pablo Neira Ayuso
  6 siblings, 1 reply; 17+ messages in thread
From: Richard Weinberger @ 2012-03-05 23:19 UTC (permalink / raw)
  To: pablo
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel,
	rostedt, Richard Weinberger

This patch introduces NETFILTER_XT_TARGET_LOG_RING.
It allows logging into various ring buffers which are
represented as pipe-like files in /proc/net/netfilter/nf_log_ring/.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/linux/netfilter/xt_LOG.h |   10 +
 include/net/netfilter/nf_log.h   |    1 +
 net/netfilter/Kconfig            |   18 +
 net/netfilter/xt_LOG.c           |  648 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 659 insertions(+), 18 deletions(-)

diff --git a/include/linux/netfilter/xt_LOG.h b/include/linux/netfilter/xt_LOG.h
index cac0790..8ac25e0 100644
--- a/include/linux/netfilter/xt_LOG.h
+++ b/include/linux/netfilter/xt_LOG.h
@@ -11,9 +11,19 @@
 #define XT_LOG_MASK		0x2f
 
 struct xt_log_info {
+        unsigned char level;
+        unsigned char logflags;
+        char prefix[30];
+};
+
+struct xt_log_info_v1 {
 	unsigned char level;
 	unsigned char logflags;
 	char prefix[30];
+
+	char ring_name[30];
+	__aligned_u64 ring_size;
+	struct xt_LOG_ring_ctx *rctx __attribute__((aligned(8)));
 };
 
 #endif /* _XT_LOG_H */
diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h
index e991bd0..18a94f9 100644
--- a/include/net/netfilter/nf_log.h
+++ b/include/net/netfilter/nf_log.h
@@ -14,6 +14,7 @@
 
 #define NF_LOG_TYPE_LOG		0x01
 #define NF_LOG_TYPE_ULOG	0x02
+#define NF_LOG_TYPE_RING	0x04
 
 struct nf_loginfo {
 	u_int8_t type;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index b895d8b..337bbad 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -533,6 +533,24 @@ config NETFILTER_XT_TARGET_LOG
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+if NETFILTER_XT_TARGET_LOG
+
+config NETFILTER_XT_TARGET_LOG_RING
+	bool  'Ring buffer support'
+	default y
+	select RING_BUFFER
+	help
+	 Using this it is possible to record packets into one or more ring buffers
+	 instead of the kernel syslog.
+	 Each ring buffer is represented as file in /proc/net/netfilter/nf_log_ring/.
+
+	 To log incoming IPv4 and IPv6 SSH packets into a ring named "ssh" use:
+	   iptables -A INPUT -p tcp --dport 22 -j LOG --ring ssh
+	   ip6tables -A INPUT -p tcp --dport 22 -j LOG --ring ssh
+
+	 Then read from /proc/net/netfilter/nf_log_ring/ssh.
+endif
+
 config NETFILTER_XT_TARGET_MARK
 	tristate '"MARK" target support'
 	depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
index f99f8de..f75f2d7 100644
--- a/net/netfilter/xt_LOG.c
+++ b/net/netfilter/xt_LOG.c
@@ -16,6 +16,21 @@
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/ip.h>
+#include <linux/ctype.h>
+#include <linux/ring_buffer.h>
+#include <linux/cpu.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/atomic.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <net/ipv6.h>
 #include <net/icmp.h>
 #include <net/udp.h>
@@ -29,6 +44,51 @@
 #include <net/netfilter/nf_log.h>
 #include <net/netfilter/xt_log.h>
 
+#ifdef CONFIG_NETFILTER_XT_TARGET_LOG_RING
+#define RING_DIR "nf_log_ring"
+
+struct xt_LOG_ring_ctx {
+	char name[32];
+	struct ring_buffer *buffer;
+	atomic_t pipe_in_use;
+	atomic_t refcnt;
+
+	struct list_head list;
+};
+
+struct rlog_entry {
+	size_t count;
+	char msg[0];
+};
+
+struct rlog_iter {
+	struct ring_buffer *buffer;
+	const char *buffer_name;
+	struct rlog_entry *ent;
+
+	char print_buf[PAGE_SIZE];
+	size_t print_buf_len;
+	size_t print_buf_pos;
+
+	unsigned long lost_events;
+	int cpu;
+
+	struct mutex lock;
+};
+
+static DEFINE_SPINLOCK(ring_list_lock);
+static LIST_HEAD(ring_list);
+static DECLARE_WAIT_QUEUE_HEAD(rlog_wait);
+static struct proc_dir_entry *prlog;
+
+static int xt_LOG_ring_add_record(const struct xt_LOG_ring_ctx *rctx,
+                           const char *buf, unsigned int len);
+static struct xt_LOG_ring_ctx *xt_LOG_ring_find_ctx(const char *name);
+static struct xt_LOG_ring_ctx *xt_LOG_ring_new_ctx(const char *name, size_t rb_size);
+static void xt_LOG_ring_get(struct xt_LOG_ring_ctx *ctx);
+static void xt_LOG_ring_put(struct xt_LOG_ring_ctx *ctx);
+#endif
+
 static struct nf_loginfo default_loginfo = {
 	.type	= NF_LOG_TYPE_LOG,
 	.u = {
@@ -155,7 +215,7 @@ static void dump_ipv4_packet(struct sbuff *m,
 	const struct iphdr *ih;
 	unsigned int logflags;
 
-	if (info->type == NF_LOG_TYPE_LOG)
+	if (info->type == NF_LOG_TYPE_LOG || info->type == NF_LOG_TYPE_RING)
 		logflags = info->u.log.logflags;
 	else
 		logflags = NF_LOG_MASK;
@@ -396,7 +456,7 @@ static void dump_ipv4_mac_header(struct sbuff *m,
 	struct net_device *dev = skb->dev;
 	unsigned int logflags = 0;
 
-	if (info->type == NF_LOG_TYPE_LOG)
+	if (info->type == NF_LOG_TYPE_LOG || info->type == NF_LOG_TYPE_RING)
 		logflags = info->u.log.logflags;
 
 	if (!(logflags & XT_LOG_MACDECODE))
@@ -436,9 +496,10 @@ log_packet_common(struct sbuff *m,
 		  const struct nf_loginfo *loginfo,
 		  const char *prefix)
 {
-	sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
-	       prefix,
-	       in ? in->name : "",
+	if (loginfo->type == NF_LOG_TYPE_LOG)
+		sb_add(m, "<%d>", loginfo->u.log.level);
+
+	sb_add(m, "%sIN=%s OUT=%s ", prefix, in ? in->name : "",
 	       out ? out->name : "");
 #ifdef CONFIG_BRIDGE_NETFILTER
 	if (skb->nf_bridge) {
@@ -456,8 +517,7 @@ log_packet_common(struct sbuff *m,
 }
 
 
-static void
-ipt_log_packet(u_int8_t pf,
+static struct sbuff *ipt_log_packet(u_int8_t pf,
 	       unsigned int hooknum,
 	       const struct sk_buff *skb,
 	       const struct net_device *in,
@@ -477,6 +537,19 @@ ipt_log_packet(u_int8_t pf,
 
 	dump_ipv4_packet(m, loginfo, skb, 0);
 
+	return m;
+}
+
+static void ipt_log_packet_logger(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 *loginfo,
+	       const char *prefix)
+{
+	struct sbuff *m = ipt_log_packet(pf, hooknum, skb, in, out, loginfo, prefix);
+
 	sb_close(m);
 }
 
@@ -495,7 +568,7 @@ static void dump_ipv6_packet(struct sbuff *m,
 	unsigned int hdrlen = 0;
 	unsigned int logflags;
 
-	if (info->type == NF_LOG_TYPE_LOG)
+	if (info->type == NF_LOG_TYPE_LOG || info->type == NF_LOG_TYPE_RING)
 		logflags = info->u.log.logflags;
 	else
 		logflags = NF_LOG_MASK;
@@ -738,7 +811,7 @@ static void dump_ipv6_mac_header(struct sbuff *m,
 	struct net_device *dev = skb->dev;
 	unsigned int logflags = 0;
 
-	if (info->type == NF_LOG_TYPE_LOG)
+	if (info->type == NF_LOG_TYPE_LOG || info->type == NF_LOG_TYPE_RING)
 		logflags = info->u.log.logflags;
 
 	if (!(logflags & XT_LOG_MACDECODE))
@@ -786,8 +859,7 @@ fallback:
 		sb_add(m, " ");
 }
 
-static void
-ip6t_log_packet(u_int8_t pf,
+static struct sbuff *ip6t_log_packet(u_int8_t pf,
 		unsigned int hooknum,
 		const struct sk_buff *skb,
 		const struct net_device *in,
@@ -807,6 +879,19 @@ ip6t_log_packet(u_int8_t pf,
 
 	dump_ipv6_packet(m, loginfo, skb, skb_network_offset(skb), 1);
 
+	return m;
+}
+
+static void ip6t_log_packet_logger(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 *loginfo,
+	       const char *prefix)
+{
+	struct sbuff *m = ip6t_log_packet(pf, hooknum, skb, in, out, loginfo, prefix);
+
 	sb_close(m);
 }
 #endif
@@ -816,22 +901,28 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_log_info *loginfo = par->targinfo;
 	struct nf_loginfo li;
+	struct sbuff *m;
 
 	li.type = NF_LOG_TYPE_LOG;
 	li.u.log.level = loginfo->level;
 	li.u.log.logflags = loginfo->logflags;
 
 	if (par->family == NFPROTO_IPV4)
-		ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in,
-			       par->out, &li, loginfo->prefix);
+		m = ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in,
+				   par->out, &li, loginfo->prefix);
 #if IS_ENABLED(CONFIG_IPV6)
 	else if (par->family == NFPROTO_IPV6)
-		ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in,
-				par->out, &li, loginfo->prefix);
+		m = ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in,
+				    par->out, &li, loginfo->prefix);
 #endif
-	else
+	else {
 		WARN_ON_ONCE(1);
+		goto out;
+	}
+
+	sb_close(m);
 
+out:
 	return XT_CONTINUE;
 }
 
@@ -855,37 +946,552 @@ static int log_tg_check(const struct xt_tgchk_param *par)
 	return 0;
 }
 
+static unsigned int
+log_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_log_info_v1 *loginfo = par->targinfo;
+	struct nf_loginfo li;
+	struct sbuff *m;
+
+#ifdef CONFIG_NETFILTER_XT_TARGET_LOG_RING
+	if (loginfo->ring_size)
+		li.type = NF_LOG_TYPE_RING;
+	else
+#endif
+		li.type = NF_LOG_TYPE_LOG;
+
+	li.u.log.level = loginfo->level;
+	li.u.log.logflags = loginfo->logflags;
+
+	if (par->family == NFPROTO_IPV4)
+		m = ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in,
+				   par->out, &li, loginfo->prefix);
+#if IS_ENABLED(CONFIG_IPV6)
+	else if (par->family == NFPROTO_IPV6)
+		m = ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in,
+				    par->out, &li, loginfo->prefix);
+#endif
+	else {
+		WARN_ON_ONCE(1);
+		goto out;
+	}
+
+#ifdef CONFIG_NETFILTER_XT_TARGET_LOG_RING
+	if (loginfo->ring_size) {
+		sb_add(m, "\n");
+		xt_LOG_ring_add_record(loginfo->rctx, m->buf, m->count);
+		__sb_close(m, 0);
+	} else
+#endif
+		sb_close(m);
+
+out:
+	return XT_CONTINUE;
+}
+
+static int log_tg_check_v1(const struct xt_tgchk_param *par)
+{
+	struct xt_log_info_v1 *loginfo = par->targinfo;
+
+	if (par->family != NFPROTO_IPV4 && par->family != NFPROTO_IPV6)
+		return -EINVAL;
+
+	if (loginfo->level >= 8) {
+		pr_debug("level %u >= 8\n", loginfo->level);
+		return -EINVAL;
+	}
+
+	if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
+		pr_debug("prefix is not null-terminated\n");
+		return -EINVAL;
+	}
+
+	/* a non-empty ring_size indicates that we're using ring_buffer */
+	if (loginfo->ring_size) {
+#ifdef CONFIG_NETFILTER_XT_TARGET_LOG_RING
+		int i;
+		struct xt_LOG_ring_ctx *rctx;
+
+		if (loginfo->ring_name[sizeof(loginfo->ring_name)-1] != '\0') {
+			pr_debug("ring_name is not null-terminated\n");
+			return -EINVAL;
+		}
+
+		if (!loginfo->ring_name[0]) {
+			pr_debug("ring_name is empty\n");
+			return -EINVAL;
+		}
+
+		for (i = 0; i < strlen(loginfo->ring_name); i++) {
+			if (!isalnum(loginfo->ring_name[i])) {
+				pr_debug("ring_name contains "
+					 "a non-alphanumeric character\n");
+				return -EINVAL;
+			}
+		}
+
+		rctx = xt_LOG_ring_find_ctx(loginfo->ring_name);
+		if (!rctx) {
+			rctx = xt_LOG_ring_new_ctx(loginfo->ring_name,
+			       loginfo->ring_size);
+			if (IS_ERR(rctx))
+				return PTR_ERR(rctx);
+		}
+
+		xt_LOG_ring_get(rctx);
+		loginfo->rctx = rctx;
+#else
+		pr_debug("Sorry, this kernel was built without CONFIG_NETFILTER_XT_TARGET_LOG_RING\n");
+		return -EINVAL;
+#endif
+	}
+
+	return 0;
+}
+
+static void log_tg_destroy_v1(const struct xt_tgdtor_param *par)
+{
+#ifdef CONFIG_NETFILTER_XT_TARGET_LOG_RING
+	const struct xt_log_info_v1 *loginfo = par->targinfo;
+	struct xt_LOG_ring_ctx *rctx = loginfo->rctx;
+
+	if (loginfo->ring_size)
+		xt_LOG_ring_put(rctx);
+#endif
+}
+
+#ifdef CONFIG_NETFILTER_XT_TARGET_LOG_RING
+static void wakeup_work_handler(struct work_struct *work)
+{
+	wake_up(&rlog_wait);
+}
+
+static DECLARE_WORK(wakeup_work, wakeup_work_handler);
+
+static void rlog_wake_up(void)
+{
+	schedule_work(&wakeup_work);
+}
+
+static int xt_LOG_ring_add_record(const struct xt_LOG_ring_ctx *rctx,
+			   const char *buf, unsigned int len)
+{
+	struct rlog_entry *entry;
+	struct ring_buffer_event *event;
+
+	event = ring_buffer_lock_reserve(rctx->buffer, sizeof(*entry) + len);
+	if (!event)
+		return 1;
+
+	entry = ring_buffer_event_data(event);
+	memcpy(entry->msg, buf, len);
+	entry->count = len;
+
+	ring_buffer_unlock_commit(rctx->buffer, event);
+	rlog_wake_up();
+
+	return 0;
+}
+
+static struct rlog_entry *peek_next_entry(struct rlog_iter *iter, int cpu,
+					  unsigned long long *ts)
+{
+	struct ring_buffer_event *event;
+
+	event = ring_buffer_peek(iter->buffer, cpu, ts, &iter->lost_events);
+
+	if (event)
+		return ring_buffer_event_data(event);
+
+	return NULL;
+}
+
+static struct rlog_entry *find_next_entry(struct rlog_iter *iter)
+{
+	struct rlog_entry *ent, *next = NULL;
+	unsigned long long next_ts = 0, ts;
+	int cpu, next_cpu = -1;
+
+	for_each_buffer_cpu (iter->buffer, cpu) {
+		if (ring_buffer_empty_cpu(iter->buffer, cpu))
+			continue;
+
+		ent = peek_next_entry(iter, cpu, &ts);
+
+		if (ent && (!next || ts < next_ts)) {
+			next = ent;
+			next_cpu = cpu;
+			next_ts = ts;
+		}
+	}
+
+	iter->cpu = next_cpu;
+
+	return next;
+}
+
+static struct rlog_iter *find_next_iter_entry(struct rlog_iter *iter)
+{
+	iter->ent = find_next_entry(iter);
+
+	if (iter->ent)
+		return iter;
+
+	return NULL;
+}
+
+static int buffer_empty(struct rlog_iter *iter)
+{
+	int cpu;
+
+	for_each_buffer_cpu (iter->buffer, cpu) {
+		if (!ring_buffer_empty_cpu(iter->buffer, cpu))
+			return 0;
+	}
+
+	return 1;
+}
+
+static ssize_t rlog_to_user(struct rlog_iter *iter, char __user *ubuf,
+			    size_t cnt)
+{
+	int ret;
+	int len;
+
+	if (!cnt)
+		goto out;
+
+	len = iter->print_buf_len - iter->print_buf_pos;
+	if (len < 1)
+		return -EBUSY;
+
+	if (cnt > len)
+		cnt = len;
+
+	ret = copy_to_user(ubuf, iter->print_buf + iter->print_buf_pos, cnt);
+	if (ret == cnt)
+		return -EFAULT;
+
+	cnt -= ret;
+	iter->print_buf_pos += cnt;
+
+out:
+	return cnt;
+}
+
+static int rlog_open_pipe(struct inode *inode, struct file *file)
+{
+	struct rlog_iter *iter;
+	struct xt_LOG_ring_ctx *tgt = PDE(inode)->data;
+	int ret = 0;
+
+	/* only one consuming reader is allowed */
+	if (atomic_cmpxchg(&tgt->pipe_in_use, 0, 1)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+	if (!iter) {
+		atomic_set(&tgt->pipe_in_use, 0);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mutex_init(&iter->lock);
+	iter->buffer = tgt->buffer;
+	iter->buffer_name = tgt->name;
+
+	file->private_data = iter;
+out:
+	return ret;
+}
+
+static unsigned int rlog_poll_pipe(struct file *file, poll_table *poll_table)
+{
+	struct rlog_iter *iter = file->private_data;
+
+	if (!buffer_empty(iter))
+		return POLLIN | POLLRDNORM;
+
+	poll_wait(file, &rlog_wait, poll_table);
+
+	if (!buffer_empty(iter))
+		return POLLIN | POLLRDNORM;
+
+	return 0;
+}
+
+static int rlog_release_pipe(struct inode *inode, struct file *file)
+{
+	struct rlog_iter *iter = file->private_data;
+	struct xt_LOG_ring_ctx *tgt = PDE(inode)->data;
+
+	mutex_destroy(&iter->lock);
+	kfree(iter);
+	atomic_set(&tgt->pipe_in_use, 0);
+
+	return 0;
+}
+
+static void wait_pipe(struct rlog_iter *iter)
+{
+	DEFINE_WAIT(wait);
+
+	prepare_to_wait(&rlog_wait, &wait, TASK_INTERRUPTIBLE);
+
+	if (buffer_empty(iter))
+		schedule();
+
+	finish_wait(&rlog_wait, &wait);
+}
+
+static int rlog_wait_pipe(struct file *file)
+{
+	struct rlog_iter *iter = file->private_data;
+
+	while (buffer_empty(iter)) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		mutex_unlock(&iter->lock);
+
+		wait_pipe(iter);
+
+		mutex_lock(&iter->lock);
+
+		if (signal_pending(current))
+			return -EINTR;
+	}
+
+	return 1;
+}
+
+static ssize_t rlog_read_pipe(struct file *file, char __user *ubuf,
+			      size_t cnt, loff_t *ppos)
+{
+	struct rlog_iter *iter = file->private_data;
+	ssize_t ret;
+
+	ret = rlog_to_user(iter, ubuf, cnt);
+	if (ret != -EBUSY)
+		goto out;
+
+	iter->print_buf_pos = 0;
+	iter->print_buf_len = 0;
+
+	if (cnt >= PAGE_SIZE)
+		cnt = PAGE_SIZE - 1;
+
+	mutex_lock(&iter->lock);
+again:
+	ret = rlog_wait_pipe(file);
+	if (ret <= 0)
+		goto out_unlock;
+
+	while (find_next_iter_entry(iter) != NULL) {
+		struct rlog_entry *ent;
+		ent = iter->ent;
+
+		if (ent->count >= PAGE_SIZE - iter->print_buf_len)
+			break;
+
+		memcpy(iter->print_buf + iter->print_buf_len, ent->msg,
+			ent->count);
+		iter->print_buf_len += ent->count;
+
+		ring_buffer_consume(iter->buffer, iter->cpu, NULL,
+			&iter->lost_events);
+		if (iter->lost_events)
+			printk(KERN_WARNING KBUILD_MODNAME ": Ring %s "
+				"lost %lu events\n", iter->buffer_name,
+				iter->lost_events);
+
+		if (iter->print_buf_len >= cnt)
+			break;
+	}
+
+	ret = rlog_to_user(iter, ubuf, cnt);
+
+	if (iter->print_buf_pos >= iter->print_buf_len) {
+		iter->print_buf_pos = 0;
+		iter->print_buf_len = 0;
+	}
+
+	if (ret == -EBUSY)
+		goto again;
+out_unlock:
+	mutex_unlock(&iter->lock);
+out:
+	return ret;
+}
+
+static const struct file_operations rlog_pipe_fops = {
+	.open		= rlog_open_pipe,
+	.poll		= rlog_poll_pipe,
+	.read		= rlog_read_pipe,
+	.release	= rlog_release_pipe,
+	.llseek		= no_llseek,
+};
+
+static struct xt_LOG_ring_ctx *xt_LOG_ring_new_ctx(const char *name, size_t rb_size)
+{
+	struct xt_LOG_ring_ctx *new;
+
+	new = kmalloc(sizeof(*new), GFP_KERNEL);
+	if (!new) {
+		new = ERR_PTR(-ENOMEM);
+
+		goto out;
+	}
+
+	new->buffer = ring_buffer_alloc(rb_size << 10, RB_FL_OVERWRITE);
+	if (!new->buffer) {
+		kfree(new);
+		new = ERR_PTR(-ENOMEM);
+
+		goto out;
+	}
+
+	strlcpy(new->name, name, sizeof new->name);
+
+	if (!proc_create_data(name, 0400, prlog, &rlog_pipe_fops, new)) {
+		ring_buffer_free(new->buffer);
+		kfree(new);
+		new = ERR_PTR(-ENOMEM);
+
+		goto out;
+	}
+
+	atomic_set(&new->pipe_in_use, 0);
+	atomic_set(&new->refcnt, 0);
+
+	spin_lock(&ring_list_lock);
+	list_add(&new->list, &ring_list);
+	spin_unlock(&ring_list_lock);
+out:
+	return new;
+}
+
+static void free_xt_LOG_ring_ctx(struct xt_LOG_ring_ctx *ctx)
+{
+	remove_proc_entry(ctx->name, prlog);
+	ring_buffer_free(ctx->buffer);
+	list_del(&ctx->list);
+	kfree(ctx);
+}
+
+static void xt_LOG_ring_get(struct xt_LOG_ring_ctx *ctx)
+{
+	atomic_inc(&ctx->refcnt);
+}
+
+static void xt_LOG_ring_put(struct xt_LOG_ring_ctx *ctx)
+{
+	if (atomic_dec_and_test(&ctx->refcnt))
+		free_xt_LOG_ring_ctx(ctx);
+}
+
+static struct xt_LOG_ring_ctx *xt_LOG_ring_find_ctx(const char *name)
+{
+	struct list_head *e;
+	struct xt_LOG_ring_ctx *tmp, *victim = NULL;
+
+	spin_lock(&ring_list_lock);
+
+	list_for_each(e, &ring_list) {
+		tmp = list_entry(e, struct xt_LOG_ring_ctx, list);
+		if (strcmp(tmp->name, name) == 0) {
+			victim = tmp;
+
+			goto out;
+		}
+	}
+
+out:
+	spin_unlock(&ring_list_lock);
+
+	return victim;
+}
+
+static void __exit xt_LOG_ring_exit(void)
+{
+	WARN_ON(!list_empty(&ring_list));
+	remove_proc_entry(RING_DIR, proc_net_netfilter);
+}
+
+static int __init xt_LOG_ring_init(void)
+{
+	prlog = proc_mkdir(RING_DIR, proc_net_netfilter);
+	if (!prlog)
+		return -ENOMEM;
+
+	return 0;
+}
+#else
+static void __exit xt_LOG_ring_exit(void)
+{
+}
+
+static int __init xt_LOG_ring_init(void)
+{
+	return 0;
+}
+#endif /* CONFIG_NETFILTER_XT_TARGET_LOG_RING */
+
 static struct xt_target log_tg_regs[] __read_mostly = {
 	{
 		.name		= "LOG",
 		.family		= NFPROTO_IPV4,
+		.revision	= 0,
 		.target		= log_tg,
 		.targetsize	= sizeof(struct xt_log_info),
 		.checkentry	= log_tg_check,
 		.me		= THIS_MODULE,
 	},
+	{
+		.name		= "LOG",
+		.family		= NFPROTO_IPV4,
+		.revision	= 1,
+		.target		= log_tg_v1,
+		.targetsize	= sizeof(struct xt_log_info_v1),
+		.checkentry	= log_tg_check_v1,
+		.destroy	= log_tg_destroy_v1,
+		.me		= THIS_MODULE,
+	},
 #if IS_ENABLED(CONFIG_IPV6)
 	{
 		.name		= "LOG",
 		.family		= NFPROTO_IPV6,
+		.revision	= 0,
 		.target		= log_tg,
 		.targetsize	= sizeof(struct xt_log_info),
 		.checkentry	= log_tg_check,
 		.me		= THIS_MODULE,
 	},
+	{
+		.name		= "LOG",
+		.family		= NFPROTO_IPV6,
+		.revision	= 1,
+		.target		= log_tg_v1,
+		.targetsize	= sizeof(struct xt_log_info_v1),
+		.checkentry	= log_tg_check_v1,
+		.destroy	= log_tg_destroy_v1,
+		.me		= THIS_MODULE,
+	},
 #endif
 };
 
 static struct nf_logger ipt_log_logger __read_mostly = {
 	.name		= "ipt_LOG",
-	.logfn		= &ipt_log_packet,
+	.logfn		= &ipt_log_packet_logger,
 	.me		= THIS_MODULE,
 };
 
 #if IS_ENABLED(CONFIG_IPV6)
 static struct nf_logger ip6t_log_logger __read_mostly = {
 	.name		= "ip6t_LOG",
-	.logfn		= &ip6t_log_packet,
+	.logfn		= &ip6t_log_packet_logger,
 	.me		= THIS_MODULE,
 };
 #endif
@@ -894,6 +1500,10 @@ static int __init log_tg_init(void)
 {
 	int ret;
 
+	ret = xt_LOG_ring_init();
+	if (ret < 0)
+		return ret;
+
 	ret = xt_register_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs));
 	if (ret < 0)
 		return ret;
@@ -912,6 +1522,7 @@ static void __exit log_tg_exit(void)
 	nf_log_unregister(&ip6t_log_logger);
 #endif
 	xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs));
+	xt_LOG_ring_exit();
 }
 
 module_init(log_tg_init);
@@ -920,6 +1531,7 @@ module_exit(log_tg_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
+MODULE_AUTHOR("Richard Weinberger <richard@nod.at>");
 MODULE_DESCRIPTION("Xtables: IPv4/IPv6 packet logging");
 MODULE_ALIAS("ipt_LOG");
 MODULE_ALIAS("ip6t_LOG");
-- 
1.7.7.3


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

* [PATCH 6/6] Netfilter: xt_LOG: Add timestamp support
  2012-03-05 23:19 [PATCH v6] Netfilter ring buffer support Richard Weinberger
                   ` (4 preceding siblings ...)
  2012-03-05 23:19 ` [PATCH 5/6] Netfilter: xt_LOG: Implement ring buffer support Richard Weinberger
@ 2012-03-05 23:19 ` Richard Weinberger
  2012-03-07 15:29   ` Pablo Neira Ayuso
  2012-03-08  1:28 ` [PATCH v6] Netfilter ring buffer support Pablo Neira Ayuso
  6 siblings, 1 reply; 17+ messages in thread
From: Richard Weinberger @ 2012-03-05 23:19 UTC (permalink / raw)
  To: pablo
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel,
	rostedt, Richard Weinberger

Using XT_LOG_ADD_TIMESTAMP it is possible to have a timestamp
directly in the log message.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/linux/netfilter/xt_LOG.h |    3 ++-
 net/netfilter/xt_LOG.c           |    8 ++++++++
 2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/include/linux/netfilter/xt_LOG.h b/include/linux/netfilter/xt_LOG.h
index 8ac25e0..9361374 100644
--- a/include/linux/netfilter/xt_LOG.h
+++ b/include/linux/netfilter/xt_LOG.h
@@ -8,7 +8,8 @@
 #define XT_LOG_UID		0x08	/* Log UID owning local socket */
 #define XT_LOG_NFLOG		0x10	/* Unsupported, don't reuse */
 #define XT_LOG_MACDECODE	0x20	/* Decode MAC header */
-#define XT_LOG_MASK		0x2f
+#define XT_LOG_ADD_TIMESTAMP	0x40    /* Add a timestamp */
+#define XT_LOG_MASK		0x6f
 
 struct xt_log_info {
         unsigned char level;
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
index f75f2d7..23db206 100644
--- a/net/netfilter/xt_LOG.c
+++ b/net/netfilter/xt_LOG.c
@@ -499,6 +499,14 @@ log_packet_common(struct sbuff *m,
 	if (loginfo->type == NF_LOG_TYPE_LOG)
 		sb_add(m, "<%d>", loginfo->u.log.level);
 
+	if (loginfo->u.log.logflags & XT_LOG_ADD_TIMESTAMP) {
+		struct timespec tv;
+
+		getnstimeofday(&tv);
+		sb_add(m, "TIMESTAMP=%li.%03u ", tv.tv_sec,
+			(unsigned int)tv.tv_nsec / NSEC_PER_MSEC);
+	}
+
 	sb_add(m, "%sIN=%s OUT=%s ", prefix, in ? in->name : "",
 	       out ? out->name : "");
 #ifdef CONFIG_BRIDGE_NETFILTER
-- 
1.7.7.3


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

* Re: [PATCH 5/6] Netfilter: xt_LOG: Implement ring buffer support
  2012-03-05 23:19 ` [PATCH 5/6] Netfilter: xt_LOG: Implement ring buffer support Richard Weinberger
@ 2012-03-06  2:47   ` Steven Rostedt
  0 siblings, 0 replies; 17+ messages in thread
From: Steven Rostedt @ 2012-03-06  2:47 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: pablo, jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel

On Tue, 2012-03-06 at 00:19 +0100, Richard Weinberger wrote:
> This patch introduces NETFILTER_XT_TARGET_LOG_RING.
> It allows logging into various ring buffers which are
> represented as pipe-like files in /proc/net/netfilter/nf_log_ring/.
> 
> Signed-off-by: Richard Weinberger <richard@nod.at> 

Acked-by: Steven Rostedt <rostedt@goodmis.org>

-- Steve



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

* Re: [PATCH 6/6] Netfilter: xt_LOG: Add timestamp support
  2012-03-05 23:19 ` [PATCH 6/6] Netfilter: xt_LOG: Add timestamp support Richard Weinberger
@ 2012-03-07 15:29   ` Pablo Neira Ayuso
  2012-03-07 15:33     ` Richard Weinberger
  2012-03-07 15:40     ` Eric Dumazet
  0 siblings, 2 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2012-03-07 15:29 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel, rostedt

On Tue, Mar 06, 2012 at 12:19:48AM +0100, Richard Weinberger wrote:
> Using XT_LOG_ADD_TIMESTAMP it is possible to have a timestamp
> directly in the log message.
> 
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  include/linux/netfilter/xt_LOG.h |    3 ++-
>  net/netfilter/xt_LOG.c           |    8 ++++++++
>  2 files changed, 10 insertions(+), 1 deletions(-)
> 
> diff --git a/include/linux/netfilter/xt_LOG.h b/include/linux/netfilter/xt_LOG.h
> index 8ac25e0..9361374 100644
> --- a/include/linux/netfilter/xt_LOG.h
> +++ b/include/linux/netfilter/xt_LOG.h
> @@ -8,7 +8,8 @@
>  #define XT_LOG_UID		0x08	/* Log UID owning local socket */
>  #define XT_LOG_NFLOG		0x10	/* Unsupported, don't reuse */
>  #define XT_LOG_MACDECODE	0x20	/* Decode MAC header */
> -#define XT_LOG_MASK		0x2f
> +#define XT_LOG_ADD_TIMESTAMP	0x40    /* Add a timestamp */
> +#define XT_LOG_MASK		0x6f
>  
>  struct xt_log_info {
>          unsigned char level;
> diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
> index f75f2d7..23db206 100644
> --- a/net/netfilter/xt_LOG.c
> +++ b/net/netfilter/xt_LOG.c
> @@ -499,6 +499,14 @@ log_packet_common(struct sbuff *m,
>  	if (loginfo->type == NF_LOG_TYPE_LOG)
>  		sb_add(m, "<%d>", loginfo->u.log.level);
>  
> +	if (loginfo->u.log.logflags & XT_LOG_ADD_TIMESTAMP) {
> +		struct timespec tv;
> +
> +		getnstimeofday(&tv);
> +		sb_add(m, "TIMESTAMP=%li.%03u ", tv.tv_sec,
> +			(unsigned int)tv.tv_nsec / NSEC_PER_MSEC);

net/netfilter/xt_LOG.c: In function ‘log_packet_common’:
net/netfilter/xt_LOG.c:507:4: warning: format ‘%u’ expects argument of
type ‘unsigned int’, but argument 4 has type ‘long int’ [-Wformat]

It has to be:

                sb_add(m, "TIMESTAMP=%li.%03u ", tv.tv_sec,
                        (unsigned int)(tv.tv_nsec / NSEC_PER_MSEC));
                                      ^                          ^
I've fixed, no need to resend this patch.

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

* Re: [PATCH 6/6] Netfilter: xt_LOG: Add timestamp support
  2012-03-07 15:29   ` Pablo Neira Ayuso
@ 2012-03-07 15:33     ` Richard Weinberger
  2012-03-07 15:40     ` Eric Dumazet
  1 sibling, 0 replies; 17+ messages in thread
From: Richard Weinberger @ 2012-03-07 15:33 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel, rostedt

On 07.03.2012 16:29, Pablo Neira Ayuso wrote:
> On Tue, Mar 06, 2012 at 12:19:48AM +0100, Richard Weinberger wrote:
>> Using XT_LOG_ADD_TIMESTAMP it is possible to have a timestamp
>> directly in the log message.
>>
>> Signed-off-by: Richard Weinberger<richard@nod.at>
>> ---
>>   include/linux/netfilter/xt_LOG.h |    3 ++-
>>   net/netfilter/xt_LOG.c           |    8 ++++++++
>>   2 files changed, 10 insertions(+), 1 deletions(-)
>>
>> diff --git a/include/linux/netfilter/xt_LOG.h b/include/linux/netfilter/xt_LOG.h
>> index 8ac25e0..9361374 100644
>> --- a/include/linux/netfilter/xt_LOG.h
>> +++ b/include/linux/netfilter/xt_LOG.h
>> @@ -8,7 +8,8 @@
>>   #define XT_LOG_UID		0x08	/* Log UID owning local socket */
>>   #define XT_LOG_NFLOG		0x10	/* Unsupported, don't reuse */
>>   #define XT_LOG_MACDECODE	0x20	/* Decode MAC header */
>> -#define XT_LOG_MASK		0x2f
>> +#define XT_LOG_ADD_TIMESTAMP	0x40    /* Add a timestamp */
>> +#define XT_LOG_MASK		0x6f
>>
>>   struct xt_log_info {
>>           unsigned char level;
>> diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
>> index f75f2d7..23db206 100644
>> --- a/net/netfilter/xt_LOG.c
>> +++ b/net/netfilter/xt_LOG.c
>> @@ -499,6 +499,14 @@ log_packet_common(struct sbuff *m,
>>   	if (loginfo->type == NF_LOG_TYPE_LOG)
>>   		sb_add(m, "<%d>", loginfo->u.log.level);
>>
>> +	if (loginfo->u.log.logflags&  XT_LOG_ADD_TIMESTAMP) {
>> +		struct timespec tv;
>> +
>> +		getnstimeofday(&tv);
>> +		sb_add(m, "TIMESTAMP=%li.%03u ", tv.tv_sec,
>> +			(unsigned int)tv.tv_nsec / NSEC_PER_MSEC);
>
> net/netfilter/xt_LOG.c: In function ‘log_packet_common’:
> net/netfilter/xt_LOG.c:507:4: warning: format ‘%u’ expects argument of
> type ‘unsigned int’, but argument 4 has type ‘long int’ [-Wformat]
>
> It has to be:
>
>                  sb_add(m, "TIMESTAMP=%li.%03u ", tv.tv_sec,
>                          (unsigned int)(tv.tv_nsec / NSEC_PER_MSEC));
>                                        ^                          ^
> I've fixed, no need to resend this patch.

Which gcc version are you using?
I've not seen this warning. :(

Thanks,
//richard

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

* Re: [PATCH 6/6] Netfilter: xt_LOG: Add timestamp support
  2012-03-07 15:29   ` Pablo Neira Ayuso
  2012-03-07 15:33     ` Richard Weinberger
@ 2012-03-07 15:40     ` Eric Dumazet
  1 sibling, 0 replies; 17+ messages in thread
From: Eric Dumazet @ 2012-03-07 15:40 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: Richard Weinberger, jengelh, linux-kernel, netdev,
	netfilter-devel, rostedt

Le mercredi 07 mars 2012 à 16:29 +0100, Pablo Neira Ayuso a écrit :
> On Tue, Mar 06, 2012 at 12:19:48AM +0100, Richard Weinberger wrote:
> > Using XT_LOG_ADD_TIMESTAMP it is possible to have a timestamp
> > directly in the log message.
> > 
> > Signed-off-by: Richard Weinberger <richard@nod.at>
> > ---
> >  include/linux/netfilter/xt_LOG.h |    3 ++-
> >  net/netfilter/xt_LOG.c           |    8 ++++++++
> >  2 files changed, 10 insertions(+), 1 deletions(-)
> > 
> > diff --git a/include/linux/netfilter/xt_LOG.h b/include/linux/netfilter/xt_LOG.h
> > index 8ac25e0..9361374 100644
> > --- a/include/linux/netfilter/xt_LOG.h
> > +++ b/include/linux/netfilter/xt_LOG.h
> > @@ -8,7 +8,8 @@
> >  #define XT_LOG_UID		0x08	/* Log UID owning local socket */
> >  #define XT_LOG_NFLOG		0x10	/* Unsupported, don't reuse */
> >  #define XT_LOG_MACDECODE	0x20	/* Decode MAC header */
> > -#define XT_LOG_MASK		0x2f
> > +#define XT_LOG_ADD_TIMESTAMP	0x40    /* Add a timestamp */
> > +#define XT_LOG_MASK		0x6f
> >  
> >  struct xt_log_info {
> >          unsigned char level;
> > diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
> > index f75f2d7..23db206 100644
> > --- a/net/netfilter/xt_LOG.c
> > +++ b/net/netfilter/xt_LOG.c
> > @@ -499,6 +499,14 @@ log_packet_common(struct sbuff *m,
> >  	if (loginfo->type == NF_LOG_TYPE_LOG)
> >  		sb_add(m, "<%d>", loginfo->u.log.level);
> >  
> > +	if (loginfo->u.log.logflags & XT_LOG_ADD_TIMESTAMP) {
> > +		struct timespec tv;
> > +
> > +		getnstimeofday(&tv);
> > +		sb_add(m, "TIMESTAMP=%li.%03u ", tv.tv_sec,
> > +			(unsigned int)tv.tv_nsec / NSEC_PER_MSEC);
> 
> net/netfilter/xt_LOG.c: In function ‘log_packet_common’:
> net/netfilter/xt_LOG.c:507:4: warning: format ‘%u’ expects argument of
> type ‘unsigned int’, but argument 4 has type ‘long int’ [-Wformat]
> 
> It has to be:
> 
>                 sb_add(m, "TIMESTAMP=%li.%03u ", tv.tv_sec,
>                         (unsigned int)(tv.tv_nsec / NSEC_PER_MSEC));
>                                       ^                          ^
> I've fixed, no need to resend this patch.

This is why I submitted the "netfilter: ipt_LOG: add __printf() to
sb_add()" patch :)




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

* Re: [PATCH v6] Netfilter ring buffer support
  2012-03-05 23:19 [PATCH v6] Netfilter ring buffer support Richard Weinberger
                   ` (5 preceding siblings ...)
  2012-03-05 23:19 ` [PATCH 6/6] Netfilter: xt_LOG: Add timestamp support Richard Weinberger
@ 2012-03-08  1:28 ` Pablo Neira Ayuso
  2012-03-08  9:02   ` Richard Weinberger
  6 siblings, 1 reply; 17+ messages in thread
From: Pablo Neira Ayuso @ 2012-03-08  1:28 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel, rostedt

On Tue, Mar 06, 2012 at 12:19:42AM +0100, Richard Weinberger wrote:
> This patch set merges ipt_LOG and ip6t_LOG and adds ring buffer support
> to xt_LOG.
> 
> Using "--ring" an user can create LOG rules which log messages into
> one or more ring buffers.
> Each ring buffer is represented as pipe-like file in
> /proc/net/netfilter/nf_log_ring/.

I've spent part of the evening testing this and checking its
possibilities, the drawbacks that I see for this contribution are:

* it uses the /proc entry, we have rejected similar add-ons in the
  past that have used these interfaces.
* one single reader can be reading at a time.

Having said that, I still think that the feature that this provides
is useful, but I think that implementing this in user-space over
nfnetlink_log results in a much more flexible solution.

I have made proof-of-concept daemon (it's a quick hack of several
hours) that implements the similar feature over nfnetlink_log,
advantages are:

* You don't need to upgrade your kernel / iptables.
* You only need to install libnfnetlink, libnetfilter_log and the
  daemon.
* It can be extended to support multiple readers.

So my conclusion is that you can make this in userspace in a much more
flexible way.

You can find it here:

http://1984.lsi.us.es/git/rlogd/

The initial commit provides some description on how to use it:

http://1984.lsi.us.es/git/rlogd/commit/?id=ccb88a8dc8ad674b860f2d3edabf07fe4830baf3

I don't plan to develop / maintain that software. The last thing I
want in my todo list is yet another thing to maintain. If someone is
interested, please, feel free to grab it, make a nice website for it
and maintain it.

The repository also contains an unfinished patch to add LOG format
support to libnetfilter_log.

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

* Re: [PATCH v6] Netfilter ring buffer support
  2012-03-08  1:28 ` [PATCH v6] Netfilter ring buffer support Pablo Neira Ayuso
@ 2012-03-08  9:02   ` Richard Weinberger
  2012-03-12 13:08     ` Pablo Neira Ayuso
  0 siblings, 1 reply; 17+ messages in thread
From: Richard Weinberger @ 2012-03-08  9:02 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel, rostedt

On 08.03.2012 02:28, Pablo Neira Ayuso wrote:
> On Tue, Mar 06, 2012 at 12:19:42AM +0100, Richard Weinberger wrote:
>> This patch set merges ipt_LOG and ip6t_LOG and adds ring buffer support
>> to xt_LOG.
>>
>> Using "--ring" an user can create LOG rules which log messages into
>> one or more ring buffers.
>> Each ring buffer is represented as pipe-like file in
>> /proc/net/netfilter/nf_log_ring/.
>
> I've spent part of the evening testing this and checking its
> possibilities, the drawbacks that I see for this contribution are:
>
> * it uses the /proc entry, we have rejected similar add-ons in the
>    past that have used these interfaces.

My fist implementation used sysfs/debug.
I've switched to /proc/net/netfilter/ to make it consistent to the other
netfilter stuff...
Moving back to sysfs/debug/whatever can be done within minutes.

> * one single reader can be reading at a time.

In which use-cache you need two _consuming_ readers?
Steve's ring_buffer supports also concurrent non-consuming reads.
I can add support for this...

> Having said that, I still think that the feature that this provides
> is useful, but I think that implementing this in user-space over
> nfnetlink_log results in a much more flexible solution.
>
> I have made proof-of-concept daemon (it's a quick hack of several
> hours) that implements the similar feature over nfnetlink_log,
> advantages are:
>
> * You don't need to upgrade your kernel / iptables.
> * You only need to install libnfnetlink, libnetfilter_log and the
>    daemon.
> * It can be extended to support multiple readers.
>
> So my conclusion is that you can make this in userspace in a much more
> flexible way.
>
> You can find it here:
>
> http://1984.lsi.us.es/git/rlogd/
>
> The initial commit provides some description on how to use it:
>
> http://1984.lsi.us.es/git/rlogd/commit/?id=ccb88a8dc8ad674b860f2d3edabf07fe4830baf3
>
> I don't plan to develop / maintain that software. The last thing I
> want in my todo list is yet another thing to maintain. If someone is
> interested, please, feel free to grab it, make a nice website for it
> and maintain it.
>
> The repository also contains an unfinished patch to add LOG format
> support to libnetfilter_log.

I really don't like this rlogd thing.

1. It's yet another random netfilter userspace component.
Please don't fragment it more.
Installing iptables/conntrack/ulogd/etc... is already enough PITA 
because not all distros ship all this clustered components.

2. As I described in my very fist RLOG patch, NFLOG does not include the 
same information.
You cannot derive "PHYSIN" and "PHYSOUT" from the packet header.

3. rlogd needs NFLOG which copies every packet (header) to userspace.
What about performance...?

Thanks,
//richard

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

* Re: [PATCH v6] Netfilter ring buffer support
  2012-03-08  9:02   ` Richard Weinberger
@ 2012-03-12 13:08     ` Pablo Neira Ayuso
  2012-03-12 13:27       ` Richard Weinberger
  0 siblings, 1 reply; 17+ messages in thread
From: Pablo Neira Ayuso @ 2012-03-12 13:08 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel, rostedt

Hi Richard,

On Thu, Mar 08, 2012 at 10:02:45AM +0100, Richard Weinberger wrote:
> On 08.03.2012 02:28, Pablo Neira Ayuso wrote:
> >On Tue, Mar 06, 2012 at 12:19:42AM +0100, Richard Weinberger wrote:
> >>This patch set merges ipt_LOG and ip6t_LOG and adds ring buffer support
> >>to xt_LOG.
> >>
> >>Using "--ring" an user can create LOG rules which log messages into
> >>one or more ring buffers.
> >>Each ring buffer is represented as pipe-like file in
> >>/proc/net/netfilter/nf_log_ring/.
> >
> >I've spent part of the evening testing this and checking its
> >possibilities, the drawbacks that I see for this contribution are:
> >
> >* it uses the /proc entry, we have rejected similar add-ons in the
> >   past that have used these interfaces.
> 
> My fist implementation used sysfs/debug.
> I've switched to /proc/net/netfilter/ to make it consistent to the other
> netfilter stuff...
>
> Moving back to sysfs/debug/whatever can be done within minutes.
>
> >* one single reader can be reading at a time.
> 
> In which use-cache you need two _consuming_ readers?

One scenario in which two sysadmins are checking the logs to debug
some issues seems reasonable to me.

Anyway, my main points after testing several your buffer-ring things
are at the bottom of this email.

> Steve's ring_buffer supports also concurrent non-consuming reads.
> I can add support for this...
> 
> >Having said that, I still think that the feature that this provides
> >is useful, but I think that implementing this in user-space over
> >nfnetlink_log results in a much more flexible solution.
> >
> >I have made proof-of-concept daemon (it's a quick hack of several
> >hours) that implements the similar feature over nfnetlink_log,
> >advantages are:
> >
> >* You don't need to upgrade your kernel / iptables.
> >* You only need to install libnfnetlink, libnetfilter_log and the
> >   daemon.
> >* It can be extended to support multiple readers.
> >
> >So my conclusion is that you can make this in userspace in a much more
> >flexible way.
> >
> >You can find it here:
> >
> >http://1984.lsi.us.es/git/rlogd/
> >
> >The initial commit provides some description on how to use it:
> >
> >http://1984.lsi.us.es/git/rlogd/commit/?id=ccb88a8dc8ad674b860f2d3edabf07fe4830baf3
> >
> >I don't plan to develop / maintain that software. The last thing I
> >want in my todo list is yet another thing to maintain. If someone is
> >interested, please, feel free to grab it, make a nice website for it
> >and maintain it.
> >
> >The repository also contains an unfinished patch to add LOG format
> >support to libnetfilter_log.
> 
> I really don't like this rlogd thing.
>
> 1. It's yet another random netfilter userspace component.
> Please don't fragment it more.

IMO modularity is a good thing, independent user-space components
allow you to just upgrade the thing that you require.

> Installing iptables/conntrack/ulogd/etc... is already enough PITA
> because not all distros ship all this clustered components.

I think that recompiling your kernel or even wait until your distro
ships the new kernel with new extensions will take longer than packaging
some small user-space software and deploying it. Not talking about
packaging a new iptables package containing support for some new
feature.

This rlogd proof-of-concept thing (and user-space stuff in general)
will:

1) not need any kernel update.
2) be very easy to make a package and to deploy.
3) require no Linux kernel update since NFLOG has been there since
   long time.

> 2. As I described in my very fist RLOG patch, NFLOG does not include
> the same information.
> You cannot derive "PHYSIN" and "PHYSOUT" from the packet header.

Looking at the code, those are included if bridging is enabled.
Otherwise, I'll be happy to take a patch for this.

> 3. rlogd needs NFLOG which copies every packet (header) to userspace.
> What about performance...?

Reliability is also important, running things in user-space means that
bugs will no crash your system. Instead, they may crash your logging
daemon.

What I find hard to justify is that this feature can be implemented in
user-space with the existing netfilter logging interface.

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

* Re: [PATCH v6] Netfilter ring buffer support
  2012-03-12 13:08     ` Pablo Neira Ayuso
@ 2012-03-12 13:27       ` Richard Weinberger
  2012-03-12 14:12         ` Pablo Neira Ayuso
  0 siblings, 1 reply; 17+ messages in thread
From: Richard Weinberger @ 2012-03-12 13:27 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel, rostedt

Pablo,

On 12.03.2012 14:08, Pablo Neira Ayuso wrote:
> Hi Richard,
>
> On Thu, Mar 08, 2012 at 10:02:45AM +0100, Richard Weinberger wrote:
>> On 08.03.2012 02:28, Pablo Neira Ayuso wrote:
>>> On Tue, Mar 06, 2012 at 12:19:42AM +0100, Richard Weinberger wrote:
>>>> This patch set merges ipt_LOG and ip6t_LOG and adds ring buffer support
>>>> to xt_LOG.
>>>>
>>>> Using "--ring" an user can create LOG rules which log messages into
>>>> one or more ring buffers.
>>>> Each ring buffer is represented as pipe-like file in
>>>> /proc/net/netfilter/nf_log_ring/.
>>>
>>> I've spent part of the evening testing this and checking its
>>> possibilities, the drawbacks that I see for this contribution are:
>>>
>>> * it uses the /proc entry, we have rejected similar add-ons in the
>>>    past that have used these interfaces.
>>
>> My fist implementation used sysfs/debug.
>> I've switched to /proc/net/netfilter/ to make it consistent to the other
>> netfilter stuff...
>>
>> Moving back to sysfs/debug/whatever can be done within minutes.
>>
>>> * one single reader can be reading at a time.
>>
>> In which use-cache you need two _consuming_ readers?
>
> One scenario in which two sysadmins are checking the logs to debug
> some issues seems reasonable to me.

But they don't need do to a consuming read.
As I said, I can add support for non-consuming reads...

> Anyway, my main points after testing several your buffer-ring things
> are at the bottom of this email.
>
>> Steve's ring_buffer supports also concurrent non-consuming reads.
>> I can add support for this...
>>
>>> Having said that, I still think that the feature that this provides
>>> is useful, but I think that implementing this in user-space over
>>> nfnetlink_log results in a much more flexible solution.
>>>
>>> I have made proof-of-concept daemon (it's a quick hack of several
>>> hours) that implements the similar feature over nfnetlink_log,
>>> advantages are:
>>>
>>> * You don't need to upgrade your kernel / iptables.
>>> * You only need to install libnfnetlink, libnetfilter_log and the
>>>    daemon.
>>> * It can be extended to support multiple readers.
>>>
>>> So my conclusion is that you can make this in userspace in a much more
>>> flexible way.
>>>
>>> You can find it here:
>>>
>>> http://1984.lsi.us.es/git/rlogd/
>>>
>>> The initial commit provides some description on how to use it:
>>>
>>> http://1984.lsi.us.es/git/rlogd/commit/?id=ccb88a8dc8ad674b860f2d3edabf07fe4830baf3
>>>
>>> I don't plan to develop / maintain that software. The last thing I
>>> want in my todo list is yet another thing to maintain. If someone is
>>> interested, please, feel free to grab it, make a nice website for it
>>> and maintain it.
>>>
>>> The repository also contains an unfinished patch to add LOG format
>>> support to libnetfilter_log.
>>
>> I really don't like this rlogd thing.
>>
>> 1. It's yet another random netfilter userspace component.
>> Please don't fragment it more.
>
> IMO modularity is a good thing, independent user-space components
> allow you to just upgrade the thing that you require.
>
>> Installing iptables/conntrack/ulogd/etc... is already enough PITA
>> because not all distros ship all this clustered components.
>
> I think that recompiling your kernel or even wait until your distro
> ships the new kernel with new extensions will take longer than packaging
> some small user-space software and deploying it. Not talking about
> packaging a new iptables package containing support for some new
> feature.
>
> This rlogd proof-of-concept thing (and user-space stuff in general)
> will:
>
> 1) not need any kernel update.
> 2) be very easy to make a package and to deploy.
> 3) require no Linux kernel update since NFLOG has been there since
>     long time.
>
>> 2. As I described in my very fist RLOG patch, NFLOG does not include
>> the same information.
>> You cannot derive "PHYSIN" and "PHYSOUT" from the packet header.
>
> Looking at the code, those are included if bridging is enabled.
> Otherwise, I'll be happy to take a patch for this.

Doesn't NFLOG just pass the packet header to userspace?
How can you derive meta-information like "PHYSIN" and "PHYSOUT" from the 
packet header?

Iff NFLOG is able to produce same log string like LOG does I'm fine.

>> 3. rlogd needs NFLOG which copies every packet (header) to userspace.
>> What about performance...?
>
> Reliability is also important, running things in user-space means that
> bugs will no crash your system. Instead, they may crash your logging
> daemon.
>
> What I find hard to justify is that this feature can be implemented in
> user-space with the existing netfilter logging interface.

I understand that I have no chance to fight against the "this can be 
done in userspace"-argument. :-)

Thanks,
//richard

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

* Re: [PATCH v6] Netfilter ring buffer support
  2012-03-12 13:27       ` Richard Weinberger
@ 2012-03-12 14:12         ` Pablo Neira Ayuso
  2012-03-12 18:00           ` Richard Weinberger
  0 siblings, 1 reply; 17+ messages in thread
From: Pablo Neira Ayuso @ 2012-03-12 14:12 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel, rostedt

On Mon, Mar 12, 2012 at 02:27:13PM +0100, Richard Weinberger wrote:
[...]
> >Looking at the code, those are included if bridging is enabled.
> >Otherwise, I'll be happy to take a patch for this.
> 
> Doesn't NFLOG just pass the packet header to userspace?

It also passes several interesting metainformation regarding the
packet to user-space as well. And it can be easily extended to add
more metainformation without breaking backward compatibility.

> How can you derive meta-information like "PHYSIN" and "PHYSOUT" from
> the packet header?

See nflog_get_physindev and nflog_get_physoutdev in libnetfilter_log.

> Iff NFLOG is able to produce same log string like LOG does I'm fine.

This is a patch yet incomplete for libnetfilter_log:

http://1984.lsi.us.es/git/rlogd/tree/libnflog.patch

It allows you to print in LOG output format. It still need to add
support for UDP, UDPlite, and so on, but that shouldn't be hard to
make.

I'd be happy if someone takes it over and finish it.

> >>3. rlogd needs NFLOG which copies every packet (header) to userspace.
> >>What about performance...?
> >
> >Reliability is also important, running things in user-space means that
> >bugs will no crash your system. Instead, they may crash your logging
> >daemon.
> >
> >What I find hard to justify is that this feature can be implemented in
> >user-space with the existing netfilter logging interface.
> 
> I understand that I have no chance to fight against the "this can be
> done in userspace"-argument. :-)

Regarding Netfilter in general, I'd specifically would like to
move towards making as many things in user-space as we can (while
evaluting performance impact, of course). We're getting a nice set of
netlink interfaces that are allowing us this. Thus, the idea is to
follow hybrid architecture: provide generic infrastructure in
kernel-space (by means of netlink), then develop specific features in
user-space.

In that direction, I expect to come up with a user-space cthelper
infrastructure soon so we can also implement helpers in user-space.

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

* Re: [PATCH v6] Netfilter ring buffer support
  2012-03-12 14:12         ` Pablo Neira Ayuso
@ 2012-03-12 18:00           ` Richard Weinberger
  0 siblings, 0 replies; 17+ messages in thread
From: Richard Weinberger @ 2012-03-12 18:00 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: jengelh, eric.dumazet, linux-kernel, netdev, netfilter-devel, rostedt

On 12.03.2012 15:12, Pablo Neira Ayuso wrote:
> On Mon, Mar 12, 2012 at 02:27:13PM +0100, Richard Weinberger wrote:
> [...]
>>> Looking at the code, those are included if bridging is enabled.
>>> Otherwise, I'll be happy to take a patch for this.
>>
>> Doesn't NFLOG just pass the packet header to userspace?
>
> It also passes several interesting metainformation regarding the
> packet to user-space as well. And it can be easily extended to add
> more metainformation without breaking backward compatibility.
>
>> How can you derive meta-information like "PHYSIN" and "PHYSOUT" from
>> the packet header?
>
> See nflog_get_physindev and nflog_get_physoutdev in libnetfilter_log.

Oh. This sounds great.

>> Iff NFLOG is able to produce same log string like LOG does I'm fine.
>
> This is a patch yet incomplete for libnetfilter_log:
>
> http://1984.lsi.us.es/git/rlogd/tree/libnflog.patch
>
> It allows you to print in LOG output format. It still need to add
> support for UDP, UDPlite, and so on, but that shouldn't be hard to
> make.
>
> I'd be happy if someone takes it over and finish it.

Okay. I'll take over it.
Stay tuned!

Thanks,
//richard

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

end of thread, other threads:[~2012-03-12 18:01 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-05 23:19 [PATCH v6] Netfilter ring buffer support Richard Weinberger
2012-03-05 23:19 ` [PATCH 1/6] Netfilter: Merge ipt_LOG and ip6_LOG into xt_LOG Richard Weinberger
2012-03-05 23:19 ` [PATCH 2/6] netfilter: xt_LOG: fix bogus extra layer-4 logging information Richard Weinberger
2012-03-05 23:19 ` [PATCH 3/6] ring_buffer: Export for_each_buffer_cpu() Richard Weinberger
2012-03-05 23:19 ` [PATCH 4/6] xt_log: Make printk() in sb_close() optional Richard Weinberger
2012-03-05 23:19 ` [PATCH 5/6] Netfilter: xt_LOG: Implement ring buffer support Richard Weinberger
2012-03-06  2:47   ` Steven Rostedt
2012-03-05 23:19 ` [PATCH 6/6] Netfilter: xt_LOG: Add timestamp support Richard Weinberger
2012-03-07 15:29   ` Pablo Neira Ayuso
2012-03-07 15:33     ` Richard Weinberger
2012-03-07 15:40     ` Eric Dumazet
2012-03-08  1:28 ` [PATCH v6] Netfilter ring buffer support Pablo Neira Ayuso
2012-03-08  9:02   ` Richard Weinberger
2012-03-12 13:08     ` Pablo Neira Ayuso
2012-03-12 13:27       ` Richard Weinberger
2012-03-12 14:12         ` Pablo Neira Ayuso
2012-03-12 18:00           ` Richard Weinberger

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).