All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] [PATCH] clean up nf_log API
@ 2006-05-10 19:10 Harald Welte
  2006-05-11  5:36 ` Gregor Maier
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Harald Welte @ 2006-05-10 19:10 UTC (permalink / raw)
  To: Netfilter Development Mailinglist; +Cc: Patrick McHardy

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

Hi!

After spending some more time with the nf_log API, I think it still
needs some further cleanup.

The main point of nf_log was to get some unfied support for packet
logging backends, independent of the ruleset.  We currently have logging
backend functionality tied to ipt_LOG, ipt_ULOG packet filter rules,
which is inflexible and unsuitable for other entities within netfilter
that want to log packets.

However, on thing that I missed during the nf_log implementation was the
fact that it was no longer possible to have some rules using LOG, some
others ULOG.  With the introduction of nf_log, it was only possible to
use only one logging mechanism at any given point in time.

Also, there was no fallback support.  If you had configured
nfnetlink_log as your backend and the admin decides to remove that
module, nothing will be logged, even though other mechanisms might be
available and present in the kernel.

Another problem was that neither the ULOG nor the LOG target supported
all of the arguments/parameters that the nfnetlink_log backend needed.
Therefore, it is practically impossible to exploit all the features 
with the current kernel.

Therefore, I now propose the following patchset, which

1) enhances 'struct nf_logger' with a list_head, usage counter a
   priority and pf field
2) cleans up the api.  we now call nf_log_[un]register() once from every
   backend.  registering doesn't mean that it's actually active.
   successive calls to nf_log_[un]bind_pf() will actually bind a given
   backend to the specified protocol family.
3) introduction of a new NFLOG target.  Only that NFLOG target supports
   all the arguments that all our backends support.
4) Adds 'fallback' support.  This means that during unbind or
   unregistration of a given backend, we check in the global list of
   logging backends and chose the one with the hightest priority that
   supports our protocol family.
4) modify ipt_LOG, ipt_ULOG, ip6t_LOG and nfnetlink_log to reflect the
   abovementioned changes.

I have implemented the NFLOG target as iptables target (not xtables) due
to 'customer need'.  However, once we decide that this patch should be
merged, I'll provide an x_tables version.

There are some open questions:

a) we only search for 'fallback' backends during unregistration/unbind.
   Should we also do this during registration?  Or whenever we receive
   a packet and don't have a backend?  Early registration might become
   problematic, since we don't really know what the user wants...
b) reference counting.  We could actually get_module / put_module the
   module that implements a specific backend rather than using our own
   use counter.

Comments welcome.

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-10 19:10 [RFC] [PATCH] clean up nf_log API Harald Welte
@ 2006-05-11  5:36 ` Gregor Maier
  2006-05-11  8:39   ` Harald Welte
  2006-05-11  6:56 ` Patrick McHardy
  2006-05-11  8:54 ` Holger Eitzenberger
  2 siblings, 1 reply; 11+ messages in thread
From: Gregor Maier @ 2006-05-11  5:36 UTC (permalink / raw)
  To: Harald Welte, Netfilter Development Mailinglist,
	Holger Eitzenberger, Patrick McHardy

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

Hi,

I wrote a patch about 2 month ago, that does something similiar.
Maybe some of it is usefull. If you are interested I would venture to 
update the patch.

The patch uses only a modified version of the normal LOG target, but I 
wanted to change this to a NF_LOG target anyway.


Regards
Gregor

[-- Attachment #2: nf-log-unification-take1.1.patch --]
[-- Type: text/plain, Size: 51934 bytes --]

[PATCH][RFC] Unifiy logging in netfilter using nf_log, take #1

Although nf_log is meant as a general logging API for netfilter, not 
every module uses it. Furthermore modules can interfere with the logging
of other modules. This patch (against net-2.6.17) tries to eliminate these
problems.
 
* Everything uses nf_log.c as logging API (excpect the obsolete ULOG targets)
* Loggers in nf_log.c are stackable. More than one logger can be registered
    per PF
* nf_loginfo struct has been changed. Instead of the type field and the
    union there is a "backends" field now that contains a bitmask specifing
    which backends should process/log this packet. 
* ipt_LOGc and ip6t_LOG.c have been splitted: 
    * xt_LOG.c  now contains the targets. The targets
        always use nf_log for logging. These should be the only
        logging targets. They take care of setting up nf_loginfo for
        logging to syslog and/or to other backends
    * ip_log_syslog.c and ip6_log_syslog.c are new and contain the
        syslog log backends. When these modules are loaded, the syslog
        backend is registered with nf_log
* The backends (nfnetlink_log, ip_log_syslog, ip6_log_syslog, ebt_LOG) check
    the backends field of nf_loginfo to see if they should handle the packet
* The ULOG targets have been changed to be self-contained and independent
    from nf_log API. They are the _only_ modules that do not use nf_log

What the LOG targets for v4 and v6 can do from a userspace / iptables 
point of view:
* Log to syslog (allows you to specify the flags)
* Log to nfnetlink_log (allows you to specify the loggroup)
* Log to syslog and nfnetlink_log
 ===> One LOG target fits all. 

Things TODO: 
* ebt_log is always using the syslog backend. Furthermore the code there
    isn't split into the syslog logger and the target
* change userspace iptables, so it can utilize the new stuff. Patch will 
    follow soon
* thoroughly test the patch

POTENTIAL PROBLEMS / ALTERNATIVE SOLUTION
* ipt_log_info and ip6t_log_info have been replaced by xt_log_info (which
    has changed in size). This means iptables must be recompiled and older
    iptables versions won't work with these changes. 
    If this is considered a problem the only solution I can think of, is
    not to change the old LOG targets and introduce a new, general purpose 
    target, that can do what the LOG target in this patch can to.

Signed-off-by: Gregor Maier <gregor@net.in.tum.de>

=====================================================================
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 4688969..53540df 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -123,22 +123,19 @@ extern struct list_head nf_hooks[NPROTO]
 #define NF_LOG_UID		0x08	/* Log UID owning local socket */
 #define NF_LOG_MASK		0x0f
 
-#define NF_LOG_TYPE_LOG		0x01
-#define NF_LOG_TYPE_ULOG	0x02
+/* make sure not to change this without changing xt_LOG.h:NF_LOG_BACKEND_* */
+#define NF_LOG_BACKEND_SYSLOG	0x01
+#define NF_LOG_BACKEND_NFLOG	0x02
+#define NF_LOG_BACKEND_MASK (NF_LOG_BACKEND_SYSLOG|NF_LOG_BACKEND_NFLOG)
 
 struct nf_loginfo {
-	u_int8_t type;
-	union {
-		struct {
-			u_int32_t copy_len;
-			u_int16_t group;
-			u_int16_t qthreshold;
-		} ulog;
-		struct {
-			u_int8_t level;
-			u_int8_t logflags;
-		} log;
-	} u;
+	u_int8_t backends; /* ORed from NF_LOG_BACKEND* */
+	/* nflog backend */
+	u_int16_t group;
+	u_int16_t qthreshold;
+	/* SYSLOG backend */
+	u_int8_t level;
+	u_int8_t logflags;
 };
 
 typedef void nf_logfn(unsigned int pf,
@@ -157,7 +154,7 @@ struct nf_logger {
 
 /* Function to register/unregister log function. */
 int nf_log_register(int pf, struct nf_logger *logger);
-int nf_log_unregister_pf(int pf);
+int nf_log_unregister_pf(int pf, struct nf_logger *logger);
 void nf_log_unregister_logger(struct nf_logger *logger);
 
 /* Calls the registered backend logging function */
diff --git a/include/linux/netfilter/xt_LOG.h b/include/linux/netfilter/xt_LOG.h
new file mode 100644
index 0000000..c3a2255
--- /dev/null
+++ b/include/linux/netfilter/xt_LOG.h
@@ -0,0 +1,43 @@
+/* iptables module for logging / LOG target
+ *
+ * (C) 2006 Gregor Maier <gregor@majordomus.org>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ * 
+*/
+#ifndef _XT_LOG_TARGET_H
+#define _XT_LOG_TARGET_H
+
+/* make sure not to change this without changing netfilter.h:XT_LOG_* (!) */
+#define XT_LOG_BACKEND_SYSLOG	0x01
+#define XT_LOG_BACKEND_NFLOG	0x02
+#define XT_LOG_BACKEND_MASK (XT_LOG_BACKEND_SYSLOG|XT_LOG_BACKEND_NFLOG)
+
+/* make sure not to change this without changing netfilter.h:XT_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_MASK		0x0f
+
+#define IPT_LOG_TCPSEQ		XT_LOG_TCPSEQ	/* Log TCP sequence numbers */
+#define IPT_LOG_TCPOPT		XT_LOG_TCPOPT	/* Log TCP options */
+#define IPT_LOG_IPOPT		XT_LOG_IPOPT	/* Log IP options */
+#define IPT_LOG_UID		XT_LOG_UID	/* Log UID owning local socket */
+#define IPT_LOG_MASK		XT_LOG_MASK
+
+#define IP6T_LOG_TCPSEQ		XT_LOG_TCPSEQ	/* Log TCP sequence numbers */
+#define IP6T_LOG_TCPOPT		XT_LOG_TCPOPT	/* Log TCP options */
+#define IP6T_LOG_IPOPT		XT_LOG_IPOPT	/* Log IP options */
+#define IP6T_LOG_UID		XT_LOG_UID	/* Log UID owning local socket */
+#define IP6T_LOG_MASK		XT_LOG_MASK
+
+struct xt_log_info {
+	u_int16_t group;
+	unsigned char backends;
+	unsigned char level;
+	unsigned char logflags;
+	char prefix[30];
+};
+
+#endif /* _XT_LOG_TARGET_H */
diff --git a/include/linux/netfilter_bridge/ebt_log.h b/include/linux/netfilter_bridge/ebt_log.h
index 96e231a..936e5d9 100644
--- a/include/linux/netfilter_bridge/ebt_log.h
+++ b/include/linux/netfilter_bridge/ebt_log.h
@@ -4,7 +4,7 @@
 #define EBT_LOG_IP 0x01 /* if the frame is made by ip, log the ip information */
 #define EBT_LOG_ARP 0x02
 #define EBT_LOG_NFLOG 0x04
-#define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP)
+#define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP | EBT_LOG_NFLOG)
 #define EBT_LOG_PREFIX_SIZE 30
 #define EBT_LOG_WATCHER "log"
 
diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile
index 8bf6d9f..905087e 100644
--- a/net/bridge/netfilter/Makefile
+++ b/net/bridge/netfilter/Makefile
@@ -29,4 +29,4 @@ obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_sna
 
 # watchers
 obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o
-obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_ulog.o
+obj-$(CONFIG_BRIDGE_EBT_ULOG) += ebt_ulog.o
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 288ff1d..a1cb46a 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -67,8 +67,13 @@ ebt_log_packet(unsigned int pf, unsigned
 {
 	unsigned int bitmask;
 
+	if (!loginfo)
+		return;  /* FIXME: we should add a default_loginfo here */
+	if (!(loginfo->backends & NF_LOG_BACKEND_SYSLOG))
+		return;
+
 	spin_lock_bh(&ebt_log_lock);
-	printk("<%c>%s IN=%s OUT=%s MAC source = ", '0' + loginfo->u.log.level,
+	printk("<%c>%s IN=%s OUT=%s MAC source = ", '0' + loginfo->level,
 	       prefix, in ? in->name : "", out ? out->name : "");
 
 	print_MAC(eth_hdr(skb)->h_source);
@@ -77,10 +82,7 @@ ebt_log_packet(unsigned int pf, unsigned
 
 	printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));
 
-	if (loginfo->type == NF_LOG_TYPE_LOG)
-		bitmask = loginfo->u.log.logflags;
-	else
-		bitmask = NF_LOG_MASK;
+	bitmask = loginfo->logflags;
 
 	if ((bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
 	   htons(ETH_P_IP)){
@@ -162,16 +164,14 @@ static void ebt_log(const struct sk_buff
 	struct ebt_log_info *info = (struct ebt_log_info *)data;
 	struct nf_loginfo li;
 
-	li.type = NF_LOG_TYPE_LOG;
-	li.u.log.level = info->loglevel;
-	li.u.log.logflags = info->bitmask;
+	li.backends = NF_LOG_BACKEND_SYSLOG; /* currently only syslog backend supported */
+	li.level = info->loglevel;
+	/* XXX: info->bitmask is 32 bit, logflas only 8 
+	 * Currently it's not a problem, since only 3 falgs are defined, but nevertheless */
+	li.logflags = info->bitmask;
 
-	if (info->bitmask & EBT_LOG_NFLOG)
-		nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
+	nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
 		              info->prefix);
-	else
-		ebt_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
-		               info->prefix);
 }
 
 static struct ebt_watcher log =
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 802baf7..d06c67d 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -218,28 +218,6 @@ alloc_failure:
 	goto unlock;
 }
 
-/* this function is registered with the netfilter core */
-static void ebt_log_packet(unsigned int pf, unsigned int hooknum,
-   const struct sk_buff *skb, const struct net_device *in,
-   const struct net_device *out, const struct nf_loginfo *li,
-   const char *prefix)
-{
-	struct ebt_ulog_info loginfo;
-
-	if (!li || li->type != NF_LOG_TYPE_ULOG) {
-		loginfo.nlgroup = EBT_ULOG_DEFAULT_NLGROUP;
-		loginfo.cprange = 0;
-		loginfo.qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD;
-		loginfo.prefix[0] = '\0';
-	} else {
-		loginfo.nlgroup = li->u.ulog.group;
-		loginfo.cprange = li->u.ulog.copy_len;
-		loginfo.qthreshold = li->u.ulog.qthreshold;
-		strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
-	}
-
-	ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
-}
 
 static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
    const struct net_device *in, const struct net_device *out,
@@ -275,12 +253,6 @@ static struct ebt_watcher ulog = {
 	.me		= THIS_MODULE,
 };
 
-static struct nf_logger ebt_ulog_logger = {
-	.name		= EBT_ULOG_WATCHER,
-	.logfn		= &ebt_log_packet,
-	.me		= THIS_MODULE,
-};
-
 static int __init init(void)
 {
 	int i, ret = 0;
@@ -306,13 +278,6 @@ static int __init init(void)
 	else if ((ret = ebt_register_watcher(&ulog)))
 		sock_release(ebtulognl->sk_socket);
 
-	if (nf_log_register(PF_BRIDGE, &ebt_ulog_logger) < 0) {
-		printk(KERN_WARNING "ebt_ulog: not logging via ulog "
-		       "since somebody else already registered for PF_BRIDGE\n");
-		/* we cannot make module load fail here, since otherwise
-		 * ebtables userspace would abort */
-	}
-
 	return ret;
 }
 
@@ -321,7 +286,6 @@ static void __exit fini(void)
 	ebt_ulog_buff_t *ub;
 	int i;
 
-	nf_log_unregister_logger(&ebt_ulog_logger);
 	ebt_unregister_watcher(&ulog);
 	for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
 		ub = &ulog_buffers[i];
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 933ee7a..a875596 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -313,6 +313,17 @@ config IP_NF_FILTER
 	  local output.  See the man page for iptables(8).
 
 	  To compile it as a module, choose M here.  If unsure, say N.
+	  
+config IP_NF_LOG_SYSLOG
+	tristate "Syslog backend for LOG target"
+	depends on IP_NF_IPTABLES
+	help
+	  This option adds a log backend, which allows you to create rules in
+	  any iptables table which records the packet header to the syslog.
+	  See NF_XTABLES_TARGET_LOG
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 
 config IP_NF_TARGET_REJECT
 	tristate "REJECT target support"
@@ -324,15 +335,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"
-	depends on IP_NF_IPTABLES
-	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 (OBSOLETE)"
 	depends on IP_NF_IPTABLES
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 3fe8092..8032d65 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -45,6 +45,9 @@ obj-$(CONFIG_IP_NF_MANGLE) += iptable_ma
 obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
 
+# Syslog backend support
+obj-$(CONFIG_IP_NF_LOG_SYSLOG) += ip_log_syslog.o
+
 # matches
 obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
@@ -68,7 +71,6 @@ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += i
 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
 obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
-obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
 obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
diff --git a/net/ipv4/netfilter/ip_log_syslog.c b/net/ipv4/netfilter/ip_log_syslog.c
new file mode 100644
index 0000000..8463ba9
--- /dev/null
+++ b/net/ipv4/netfilter/ip_log_syslog.c
@@ -0,0 +1,437 @@
+/*
+ * 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.
+ *
+ * 2006-03-04 Gregor Maier <greogr@majordomus.org>
+ * 	Unified logging. Use nf_log for everything. Create xt_LOG target
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.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/xt_LOG.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+MODULE_DESCRIPTION("iptables syslog logging module");
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* Use lock to serialize, so printks don't overlap */
+static DEFINE_SPINLOCK(log_lock);
+
+/* One level of recursion won't kill us */
+static void dump_packet(const struct nf_loginfo *info,
+			const struct sk_buff *skb,
+			unsigned int iphoff)
+{
+	struct iphdr _iph, *ih;
+	unsigned int logflags;
+
+	logflags = info->logflags;
+
+	ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
+	if (ih == NULL) {
+		printk("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 " */
+	printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
+	       NIPQUAD(ih->saddr), NIPQUAD(ih->daddr));
+
+	/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
+	printk("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)
+		printk("CE ");
+	if (ntohs(ih->frag_off) & IP_DF)
+		printk("DF ");
+	if (ntohs(ih->frag_off) & IP_MF)
+		printk("MF ");
+
+	/* Max length: 11 "FRAG:65535 " */
+	if (ntohs(ih->frag_off) & IP_OFFSET)
+		printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
+
+	if ((logflags & XT_LOG_IPOPT)
+	    && ih->ihl * 4 > sizeof(struct iphdr)) {
+		unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op;
+		unsigned int i, optsize;
+
+		optsize = ih->ihl * 4 - sizeof(struct iphdr);
+		op = skb_header_pointer(skb, iphoff+sizeof(_iph),
+					optsize, _opt);
+		if (op == NULL) {
+			printk("TRUNCATED");
+			return;
+		}
+
+		/* Max length: 127 "OPT (" 15*4*2chars ") " */
+		printk("OPT (");
+		for (i = 0; i < optsize; i++)
+			printk("%02X", op[i]);
+		printk(") ");
+	}
+
+	switch (ih->protocol) {
+	case IPPROTO_TCP: {
+		struct tcphdr _tcph, *th;
+
+		/* Max length: 10 "PROTO=TCP " */
+		printk("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) {
+			printk("INCOMPLETE [%u bytes] ",
+			       skb->len - iphoff - ih->ihl*4);
+			break;
+		}
+
+		/* Max length: 20 "SPT=65535 DPT=65535 " */
+		printk("SPT=%u DPT=%u ",
+		       ntohs(th->source), ntohs(th->dest));
+		/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
+		if (logflags & XT_LOG_TCPSEQ)
+			printk("SEQ=%u ACK=%u ",
+			       ntohl(th->seq), ntohl(th->ack_seq));
+		/* Max length: 13 "WINDOW=65535 " */
+		printk("WINDOW=%u ", ntohs(th->window));
+		/* Max length: 9 "RES=0x3F " */
+		printk("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)
+			printk("CWR ");
+		if (th->ece)
+			printk("ECE ");
+		if (th->urg)
+			printk("URG ");
+		if (th->ack)
+			printk("ACK ");
+		if (th->psh)
+			printk("PSH ");
+		if (th->rst)
+			printk("RST ");
+		if (th->syn)
+			printk("SYN ");
+		if (th->fin)
+			printk("FIN ");
+		/* Max length: 11 "URGP=65535 " */
+		printk("URGP=%u ", ntohs(th->urg_ptr));
+
+		if ((logflags & XT_LOG_TCPOPT)
+		    && th->doff * 4 > sizeof(struct tcphdr)) {
+			unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
+			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) {
+				printk("TRUNCATED");
+				return;
+			}
+
+			/* Max length: 127 "OPT (" 15*4*2chars ") " */
+			printk("OPT (");
+			for (i = 0; i < optsize; i++)
+				printk("%02X", op[i]);
+			printk(") ");
+		}
+		break;
+	}
+	case IPPROTO_UDP: {
+		struct udphdr _udph, *uh;
+
+		/* Max length: 10 "PROTO=UDP " */
+		printk("PROTO=UDP ");
+
+		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) {
+			printk("INCOMPLETE [%u bytes] ",
+			       skb->len - iphoff - ih->ihl*4);
+			break;
+		}
+
+		/* Max length: 20 "SPT=65535 DPT=65535 " */
+		printk("SPT=%u DPT=%u LEN=%u ",
+		       ntohs(uh->source), ntohs(uh->dest),
+		       ntohs(uh->len));
+		break;
+	}
+	case IPPROTO_ICMP: {
+		struct icmphdr _icmph, *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 " */
+		printk("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) {
+			printk("INCOMPLETE [%u bytes] ",
+			       skb->len - iphoff - ih->ihl*4);
+			break;
+		}
+
+		/* Max length: 18 "TYPE=255 CODE=255 " */
+		printk("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]) {
+			printk("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 " */
+			printk("ID=%u SEQ=%u ",
+			       ntohs(ich->un.echo.id),
+			       ntohs(ich->un.echo.sequence));
+			break;
+
+		case ICMP_PARAMETERPROB:
+			/* Max length: 14 "PARAMETER=255 " */
+			printk("PARAMETER=%u ",
+			       ntohl(ich->un.gateway) >> 24);
+			break;
+		case ICMP_REDIRECT:
+			/* Max length: 24 "GATEWAY=255.255.255.255 " */
+			printk("GATEWAY=%u.%u.%u.%u ",
+			       NIPQUAD(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. */
+				printk("[");
+				dump_packet(info, skb,
+					    iphoff + ih->ihl*4+sizeof(_icmph));
+				printk("] ");
+			}
+
+			/* Max length: 10 "MTU=65535 " */
+			if (ich->type == ICMP_DEST_UNREACH
+			    && ich->code == ICMP_FRAG_NEEDED)
+				printk("MTU=%u ", ntohs(ich->un.frag.mtu));
+		}
+		break;
+	}
+	/* Max Length */
+	case IPPROTO_AH: {
+		struct ip_auth_hdr _ahdr, *ah;
+
+		if (ntohs(ih->frag_off) & IP_OFFSET)
+			break;
+		
+		/* Max length: 9 "PROTO=AH " */
+		printk("PROTO=AH ");
+
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
+					sizeof(_ahdr), &_ahdr);
+		if (ah == NULL) {
+			printk("INCOMPLETE [%u bytes] ",
+			       skb->len - iphoff - ih->ihl*4);
+			break;
+		}
+
+		/* Length: 15 "SPI=0xF1234567 " */
+		printk("SPI=0x%x ", ntohl(ah->spi));
+		break;
+	}
+	case IPPROTO_ESP: {
+		struct ip_esp_hdr _esph, *eh;
+
+		/* Max length: 10 "PROTO=ESP " */
+		printk("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) {
+			printk("INCOMPLETE [%u bytes] ",
+			       skb->len - iphoff - ih->ihl*4);
+			break;
+		}
+
+		/* Length: 15 "SPI=0xF1234567 " */
+		printk("SPI=0x%x ", ntohl(eh->spi));
+		break;
+	}
+	/* Max length: 10 "PROTO 255 " */
+	default:
+		printk("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)
+ 			printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
+		read_unlock_bh(&skb->sk->sk_callback_lock);
+	}
+
+	/* 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 */
+	/* 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 struct nf_loginfo default_loginfo = {
+	.backends = NF_LOG_BACKEND_SYSLOG,
+	.level    = 0,
+	.logflags = NF_LOG_MASK,
+	/* other fields ignores, since only using SYSLOG backend */
+};
+
+static void
+ip_log_syslog_packet(unsigned int 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)
+{
+	/* Syslog backend is responsible if no loginfo has be specified */
+	if (!loginfo)
+		loginfo = &default_loginfo;
+	/* Are we responsible for this packet ? */
+	if (!(loginfo->backends & NF_LOG_BACKEND_SYSLOG))
+		return;
+
+	spin_lock_bh(&log_lock);
+	printk("<%d>%sIN=%s OUT=%s ", loginfo->level,
+	       prefix,
+	       in ? in->name : "",
+	       out ? out->name : "");
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge) {
+		struct net_device *physindev = skb->nf_bridge->physindev;
+		struct net_device *physoutdev = skb->nf_bridge->physoutdev;
+
+		if (physindev && in != physindev)
+			printk("PHYSIN=%s ", physindev->name);
+		if (physoutdev && out != physoutdev)
+			printk("PHYSOUT=%s ", physoutdev->name);
+	}
+#endif
+
+	if (in && !out) {
+		/* MAC logging for input chain only. */
+		printk("MAC=");
+		if (skb->dev && skb->dev->hard_header_len
+		    && skb->mac.raw != (void*)skb->nh.iph) {
+			int i;
+			unsigned char *p = skb->mac.raw;
+			for (i = 0; i < skb->dev->hard_header_len; i++,p++)
+				printk("%02x%c", *p,
+				       i==skb->dev->hard_header_len - 1
+				       ? ' ':':');
+		} else
+			printk(" ");
+	}
+
+	dump_packet(loginfo, skb, 0);
+	printk("\n");
+	spin_unlock_bh(&log_lock);
+}
+
+static struct nf_logger ip_syslog_logger ={
+	.name		= "ip_log_syslog",
+	.logfn		= &ip_log_syslog_packet,
+	.me		= THIS_MODULE,
+};
+
+static int __init init(void)
+{
+	if (nf_log_register(PF_INET, &ip_syslog_logger) < 0) {
+		printk(KERN_WARNING "ip_log_syslog: not logging via system console "
+		       "since somebody else already registered for PF_INET\n");
+		/* we cannot make module load fail here, since otherwise
+		 * iptables userspace would abort */
+	}
+	
+	return 0;
+}
+
+static void __exit fini(void)
+{
+	nf_log_unregister_logger(&ip_syslog_logger);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index a82a32e..1c184c7 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -15,6 +15,7 @@
  * 2002/10/30 fix uninitialized mac_len field - <Anders K. Pedersen>
  * 2004/10/25 fix erroneous calculation of 'len' parameter to NLMSG_PUT
  *	      resulting in bogus 'error during NLMSG_PUT' messages.
+ *	2006/03/04 make ULOG self-contained without interaction with nf_log
  *
  * (C) 1999-2001 Paul `Rusty' Russell
  * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
@@ -313,31 +314,6 @@ static unsigned int ipt_ulog_target(stru
  	return IPT_CONTINUE;
 }
  
-static void ipt_logfn(unsigned int pf,
-		      unsigned int hooknum,
-		      const struct sk_buff *skb,
-		      const struct net_device *in,
-		      const struct net_device *out,
-		      const struct nf_loginfo *li,
-		      const char *prefix)
-{
-	struct ipt_ulog_info loginfo;
-
-	if (!li || li->type != NF_LOG_TYPE_ULOG) {
-		loginfo.nl_group = ULOG_DEFAULT_NLGROUP;
-		loginfo.copy_range = 0;
-		loginfo.qthreshold = ULOG_DEFAULT_QTHRESHOLD;
-		loginfo.prefix[0] = '\0';
-	} else {
-		loginfo.nl_group = li->u.ulog.group;
-		loginfo.copy_range = li->u.ulog.copy_len;
-		loginfo.qthreshold = li->u.ulog.qthreshold;
-		strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
-	}
-
-	ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
-}
-
 static int ipt_ulog_checkentry(const char *tablename,
 			       const void *e,
 			       const struct xt_target *target,
@@ -368,12 +344,6 @@ static struct ipt_target ipt_ulog_reg = 
 	.me		= THIS_MODULE,
 };
 
-static struct nf_logger ipt_ulog_logger = {
-	.name		= "ipt_ULOG",
-	.logfn		= ipt_logfn,
-	.me		= THIS_MODULE,
-};
-
 static int __init init(void)
 {
 	int i;
@@ -401,8 +371,6 @@ static int __init init(void)
 		sock_release(nflognl->sk_socket);
 		return -EINVAL;
 	}
-	if (nflog)
-		nf_log_register(PF_INET, &ipt_ulog_logger);
 	
 	return 0;
 }
@@ -414,8 +382,6 @@ static void __exit fini(void)
 
 	DEBUGP("ipt_ULOG: cleanup_module\n");
 
-	if (nflog)
-		nf_log_unregister_logger(&ipt_ulog_logger);
 	ipt_unregister_target(&ipt_ulog_reg);
 	sock_release(nflognl->sk_socket);
 
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 98f7875..db49c5c 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -144,15 +144,17 @@ config IP6_NF_FILTER
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP6_NF_TARGET_LOG
-	tristate "LOG target support"
-	depends on IP6_NF_FILTER
+config IP6_NF_LOG_SYSLOG
+	tristate "Syslog backend for LOG target"
+	depends on IP_NF_IPTABLES
 	help
-	  This option adds a `LOG' target, which allows you to create rules in
+	  This option adds a log backend, which allows you to create rules in
 	  any iptables table which records the packet header to the syslog.
+	  See NF_XTABLES_TARGET_LOG
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+
 config IP6_NF_TARGET_REJECT
 	tristate "REJECT target support"
 	depends on IP6_NF_FILTER
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 8436a1a..418dfa4 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -4,6 +4,7 @@
 
 # Link order matters here.
 obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
+obj-$(CONFIG_IP6_NF_LOG_SYSLOG) += ip6_log_syslog.o
 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
@@ -16,7 +17,6 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
 obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
-obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
diff --git a/net/ipv6/netfilter/ip6_log_syslog.c b/net/ipv6/netfilter/ip6_log_syslog.c
new file mode 100644
index 0000000..0a1d62c
--- /dev/null
+++ b/net/ipv6/netfilter/ip6_log_syslog.c
@@ -0,0 +1,449 @@
+/*
+ * 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.
+ *
+ * 2006-03-04 Gregor Maier <greogr@majordomus.org>
+ * 	Unified logging. Use nf_log for everything. Create xt_LOG target
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.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_ipv6/ip6_tables.h>
+
+MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
+MODULE_DESCRIPTION("IP6 tables syslog logging module");
+MODULE_LICENSE("GPL");
+
+struct in_device;
+#include <net/route.h>
+#include <linux/netfilter/xt_LOG.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* Use lock to serialize, so printks don't overlap */
+static DEFINE_SPINLOCK(log_lock);
+
+/* One level of recursion won't kill us */
+static void dump_packet(const struct nf_loginfo *info,
+			const struct sk_buff *skb, unsigned int ip6hoff,
+			int recurse)
+{
+	u_int8_t currenthdr;
+	int fragment;
+	struct ipv6hdr _ip6h, *ih;
+	unsigned int ptr;
+	unsigned int hdrlen = 0;
+	unsigned int logflags;
+
+	logflags = info->logflags;
+
+	ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
+	if (ih == NULL) {
+		printk("TRUNCATED");
+		return;
+	}
+
+	/* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
+	printk("SRC=" NIP6_FMT " DST=" NIP6_FMT " ", NIP6(ih->saddr), NIP6(ih->daddr));
+
+	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
+	printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
+	       ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
+	       (ntohl(*(u_int32_t *)ih) & 0x0ff00000) >> 20,
+	       ih->hop_limit,
+	       (ntohl(*(u_int32_t *)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, *hp;
+
+		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+		if (hp == NULL) {
+			printk("TRUNCATED");
+			return;
+		}
+
+		/* Max length: 48 "OPT (...) " */
+		if (logflags & XT_LOG_IPOPT)
+			printk("OPT ( ");
+
+		switch (currenthdr) {
+		case IPPROTO_FRAGMENT: {
+			struct frag_hdr _fhdr, *fh;
+
+			printk("FRAG:");
+			fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
+						&_fhdr);
+			if (fh == NULL) {
+				printk("TRUNCATED ");
+				return;
+			}
+
+			/* Max length: 6 "65535 " */
+			printk("%u ", ntohs(fh->frag_off) & 0xFFF8);
+
+			/* Max length: 11 "INCOMPLETE " */
+			if (fh->frag_off & htons(0x0001))
+				printk("INCOMPLETE ");
+
+			printk("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)
+					printk(")");
+				return;
+			}
+			hdrlen = ipv6_optlen(hp);
+			break;
+		/* Max Length */
+		case IPPROTO_AH:
+			if (logflags & XT_LOG_IPOPT) {
+				struct ip_auth_hdr _ahdr, *ah;
+
+				/* Max length: 3 "AH " */
+				printk("AH ");
+
+				if (fragment) {
+					printk(")");
+					return;
+				}
+
+				ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
+							&_ahdr);
+				if (ah == NULL) {
+					/*
+					 * Max length: 26 "INCOMPLETE [65535 	
+					 *  bytes] )"
+					 */
+					printk("INCOMPLETE [%u bytes] )",
+					       skb->len - ptr);
+					return;
+				}
+
+				/* Length: 15 "SPI=0xF1234567 */
+				printk("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, *eh;
+
+				/* Max length: 4 "ESP " */
+				printk("ESP ");
+
+				if (fragment) {
+					printk(")");
+					return;
+				}
+
+				/*
+				 * Max length: 26 "INCOMPLETE [65535 bytes] )"
+				 */
+				eh = skb_header_pointer(skb, ptr, sizeof(_esph),
+							&_esph);
+				if (eh == NULL) {
+					printk("INCOMPLETE [%u bytes] )",
+					       skb->len - ptr);
+					return;
+				}
+
+				/* Length: 16 "SPI=0xF1234567 )" */
+				printk("SPI=0x%x )", ntohl(eh->spi) );
+
+			}
+			return;
+		default:
+			/* Max length: 20 "Unknown Ext Hdr 255" */
+			printk("Unknown Ext Hdr %u", currenthdr);
+			return;
+		}
+		if (logflags & XT_LOG_IPOPT)
+			printk(") ");
+
+		currenthdr = hp->nexthdr;
+		ptr += hdrlen;
+	}
+
+	switch (currenthdr) {
+	case IPPROTO_TCP: {
+		struct tcphdr _tcph, *th;
+
+		/* Max length: 10 "PROTO=TCP " */
+		printk("PROTO=TCP ");
+
+		if (fragment)
+			break;
+
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph);
+		if (th == NULL) {
+			printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+			return;
+		}
+
+		/* Max length: 20 "SPT=65535 DPT=65535 " */
+		printk("SPT=%u DPT=%u ",
+		       ntohs(th->source), ntohs(th->dest));
+		/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
+		if (logflags & XT_LOG_TCPSEQ)
+			printk("SEQ=%u ACK=%u ",
+			       ntohl(th->seq), ntohl(th->ack_seq));
+		/* Max length: 13 "WINDOW=65535 " */
+		printk("WINDOW=%u ", ntohs(th->window));
+		/* Max length: 9 "RES=0x3C " */
+		printk("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)
+			printk("CWR ");
+		if (th->ece)
+			printk("ECE ");
+		if (th->urg)
+			printk("URG ");
+		if (th->ack)
+			printk("ACK ");
+		if (th->psh)
+			printk("PSH ");
+		if (th->rst)
+			printk("RST ");
+		if (th->syn)
+			printk("SYN ");
+		if (th->fin)
+			printk("FIN ");
+		/* Max length: 11 "URGP=65535 " */
+		printk("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)], *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) {
+				printk("OPT (TRUNCATED)");
+				return;
+			}
+
+			/* Max length: 127 "OPT (" 15*4*2chars ") " */
+			printk("OPT (");
+			for (i =0; i < optsize; i++)
+				printk("%02X", op[i]);
+			printk(") ");
+		}
+		break;
+	}
+	case IPPROTO_UDP: {
+		struct udphdr _udph, *uh;
+
+		/* Max length: 10 "PROTO=UDP " */
+		printk("PROTO=UDP ");
+
+		if (fragment)
+			break;
+
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph);
+		if (uh == NULL) {
+			printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+			return;
+		}
+
+		/* Max length: 20 "SPT=65535 DPT=65535 " */
+		printk("SPT=%u DPT=%u LEN=%u ",
+		       ntohs(uh->source), ntohs(uh->dest),
+		       ntohs(uh->len));
+		break;
+	}
+	case IPPROTO_ICMPV6: {
+		struct icmp6hdr _icmp6h, *ic;
+
+		/* Max length: 13 "PROTO=ICMPv6 " */
+		printk("PROTO=ICMPv6 ");
+
+		if (fragment)
+			break;
+
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
+		if (ic == NULL) {
+			printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+			return;
+		}
+
+		/* Max length: 18 "TYPE=255 CODE=255 " */
+		printk("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 " */
+			printk("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 " */
+			printk("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) {
+				printk("[");
+				dump_packet(info, skb, ptr + sizeof(_icmp6h),
+					    0);
+				printk("] ");
+			}
+
+			/* Max length: 10 "MTU=65535 " */
+			if (ic->icmp6_type == ICMPV6_PKT_TOOBIG)
+				printk("MTU=%u ", ntohl(ic->icmp6_mtu));
+		}
+		break;
+	}
+	/* Max length: 10 "PROTO=255 " */
+	default:
+		printk("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)
+			printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
+		read_unlock_bh(&skb->sk->sk_callback_lock);
+	}
+}
+
+static struct nf_loginfo default_loginfo = {
+	.backends = NF_LOG_BACKEND_SYSLOG,
+	.level	  = 0,
+	.logflags = NF_LOG_MASK,
+	/* other fields ignores, since only using SYSLOG backend */
+};
+
+static void
+ip6_log_syslog_packet(unsigned int 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)
+{
+	/* Syslog backend is responsible if no loginfo has be specified */
+	if (!loginfo)
+		loginfo = &default_loginfo;
+	/* Are we responsible for this packet ? */
+	if (!(loginfo->backends & NF_LOG_BACKEND_SYSLOG))
+		return;
+
+	spin_lock_bh(&log_lock);
+	printk("<%d>%sIN=%s OUT=%s ", loginfo->level, 
+		prefix,
+		in ? in->name : "",
+		out ? out->name : "");
+	if (in && !out) {
+		unsigned int len;
+		/* MAC logging for input chain only. */
+		printk("MAC=");
+		if (skb->dev && (len = skb->dev->hard_header_len) &&
+		    skb->mac.raw != skb->nh.raw) {
+			unsigned char *p = skb->mac.raw;
+			int i;
+
+			if (skb->dev->type == ARPHRD_SIT &&
+			    (p -= ETH_HLEN) < skb->head)
+				p = NULL;
+
+			if (p != NULL) {
+				for (i = 0; i < len; i++)
+					printk("%02x%s", p[i],
+					       i == len - 1 ? "" : ":");
+			}
+			printk(" ");
+
+			if (skb->dev->type == ARPHRD_SIT) {
+				struct iphdr *iph = (struct iphdr *)skb->mac.raw;
+				printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ",
+				       NIPQUAD(iph->saddr),
+				       NIPQUAD(iph->daddr));
+			}
+		} else
+			printk(" ");
+	}
+
+	dump_packet(loginfo, skb, (u8*)skb->nh.ipv6h - skb->data, 1);
+	printk("\n");
+	spin_unlock_bh(&log_lock);
+}
+
+static struct nf_logger ip6_syslog_logger = {
+	.name		= "ip6_log_syslog",
+	.logfn		= &ip6_log_syslog_packet,
+	.me		= THIS_MODULE,
+};
+
+static int __init init(void)
+{
+	if (nf_log_register(PF_INET6, &ip6_syslog_logger) < 0) {
+		printk(KERN_WARNING "ip6_log_syslog: not logging via system console "
+		       "since somebody else already registered for PF_INET6\n");
+		/* we cannot make module load fail here, since otherwise
+		 * ip6tables userspace would abort */
+	}
+
+	return 0;
+}
+
+static void __exit fini(void)
+{
+	nf_log_unregister_logger(&ip6_syslog_logger);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 1e6e311..e66fb3a 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -136,6 +136,17 @@ config NETFILTER_XT_TARGET_CONNMARK
 	  <file:Documentation/modules.txt>.  The module will be called
 	  ipt_CONNMARK.o.  If unsure, say `N'.
 
+config NETFILTER_XT_TARGET_LOG
+	tristate '"LOG" target Support'
+	depends on NETFILTER_XTABLES
+	help
+	  This option adds a `LOG' target, which allows you to create rules in
+	  any iptables table which records the packet registered loggers like
+	  NETFILTER_NETLINK_LOG, IP_NF_LOG_SYSLOG or IP6_NF_LOG_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_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 9558727..f84601f 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tab
 # targets
 obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 3e76bd0..7a7ddb4 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -6,6 +6,8 @@
 #include <linux/skbuff.h>
 #include <linux/netfilter.h>
 #include <linux/seq_file.h>
+#include <linux/list.h>
+#include <linux/slab.h> /* for kmalloc */
 #include <net/protocol.h>
 
 #include "nf_internals.h"
@@ -15,14 +17,19 @@
 
 #define NF_LOG_PREFIXLEN		128
 
-static struct nf_logger *nf_logging[NPROTO]; /* = NULL */
+struct nf_logging_node {
+	struct list_head list;
+	struct nf_logger *logger;
+};
+
+static struct list_head nf_logging[NPROTO]; /* = NULL */
 static DEFINE_SPINLOCK(nf_log_lock);
 
-/* return EBUSY if somebody else is registered, EEXIST if the same logger
- * is registred, 0 on success. */
+/* EEXIST if the same logger is registred, 0 on success. */
 int nf_log_register(int pf, struct nf_logger *logger)
 {
-	int ret = -EBUSY;
+	struct nf_logging_node *node;
+	int ret = 0;
 
 	if (pf >= NPROTO)
 		return -EINVAL;
@@ -30,28 +37,50 @@ int nf_log_register(int pf, struct nf_lo
 	/* Any setup of logging members must be done before
 	 * substituting pointer. */
 	spin_lock(&nf_log_lock);
-	if (!nf_logging[pf]) {
-		rcu_assign_pointer(nf_logging[pf], logger);
-		ret = 0;
-	} else if (nf_logging[pf] == logger)
-		ret = -EEXIST;
-
+	/* Check if we are already registered */
+	list_for_each_entry(node, &nf_logging[pf], list) {
+		if (node->logger == logger) {
+			ret = -EEXIST;
+			goto reg_out;
+		}
+	}
+	node = kmalloc(sizeof(struct nf_logging_node), GFP_KERNEL);
+	if (!node) {
+		ret = -ENOMEM;
+		goto reg_out;
+	}
+	node->logger = logger;
+	list_add_rcu(&node->list, &nf_logging[pf]);
+	
+reg_out:
 	spin_unlock(&nf_log_lock);
+	synchronize_net();
 	return ret;
 }		
 EXPORT_SYMBOL(nf_log_register);
 
-int nf_log_unregister_pf(int pf)
+int nf_log_unregister_pf(int pf, struct nf_logger *logger)
 {
+	struct nf_logging_node *node; 
+	int do_kfree = 0;
+	
 	if (pf >= NPROTO)
 		return -EINVAL;
 
 	spin_lock(&nf_log_lock);
-	nf_logging[pf] = NULL;
+	list_for_each_entry(node, &nf_logging[pf], list) {
+		if (node->logger == logger) {
+			list_del_rcu(&node->list);
+			do_kfree=1;
+			break;
+		}
+	}
 	spin_unlock(&nf_log_lock);
 
 	/* Give time to concurrent readers. */
 	synchronize_net();
+	if (do_kfree)
+		kfree(node);
 
 	return 0;
 }
@@ -61,14 +90,10 @@ void nf_log_unregister_logger(struct nf_
 {
 	int i;
 
-	spin_lock(&nf_log_lock);
 	for (i = 0; i < NPROTO; i++) {
-		if (nf_logging[i] == logger)
-			nf_logging[i] = NULL;
+		nf_log_unregister_pf(i, logger);
 	}
-	spin_unlock(&nf_log_lock);
 
-	synchronize_net();
 }
 EXPORT_SYMBOL(nf_log_unregister_logger);
 
@@ -82,20 +107,25 @@ void nf_log_packet(int pf,
 {
 	va_list args;
 	char prefix[NF_LOG_PREFIXLEN];
-	struct nf_logger *logger;
+	struct nf_logging_node *node;
+	
+	if (pf >= NPROTO)
+		return;
 	
+	va_start(args, fmt);
+	vsnprintf(prefix, sizeof(prefix), fmt, args);
+	va_end(args);
+
 	rcu_read_lock();
-	logger = rcu_dereference(nf_logging[pf]);
-	if (logger) {
-		va_start(args, fmt);
-		vsnprintf(prefix, sizeof(prefix), fmt, args);
-		va_end(args);
-		/* We must read logging before nf_logfn[pf] */
-		logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
-	} else if (net_ratelimit()) {
+	if (list_empty(&nf_logging[pf]) && net_ratelimit()) {
 		printk(KERN_WARNING "nf_log_packet: can\'t log since "
 		       "no backend logging module loaded in! Please either "
 		       "load one, or disable logging explicitly\n");
+		rcu_read_unlock();
+		return;
+	}
+	list_for_each_entry_rcu(node, &nf_logging[pf], list) {
+		node->logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
 	}
 	rcu_read_unlock();
 }
@@ -130,14 +160,20 @@ static void seq_stop(struct seq_file *s,
 static int seq_show(struct seq_file *s, void *v)
 {
 	loff_t *pos = v;
-	const struct nf_logger *logger;
+	struct nf_logging_node *node;
 
-	logger = rcu_dereference(nf_logging[*pos]);
 
-	if (!logger)
+	if (list_empty(&nf_logging[*pos])) 
 		return seq_printf(s, "%2lld NONE\n", *pos);
+	if  (seq_printf(s, "%2lld", *pos) < 0)
+		return -1;
+
+	list_for_each_entry_rcu(node, &nf_logging[*pos], list) {
+		if (seq_printf(s, " %s", node->logger->name) < 0)
+			return -1; 
+	}
 	
-	return seq_printf(s, "%2lld %s\n", *pos, logger->name);
+	return seq_putc(s, '\n');
 }
 
 static struct seq_operations nflog_seq_ops = {
@@ -165,6 +201,8 @@ static struct file_operations nflog_file
 
 int __init netfilter_log_init(void)
 {
+	int i;
+
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *pde;
 
@@ -174,5 +212,9 @@ int __init netfilter_log_init(void)
 
 	pde->proc_fops = &nflog_file_ops;
 #endif
+
+	for (i = 0; i < NPROTO; i++) {
+		INIT_LIST_HEAD(&nf_logging[i]);
+	}
 	return 0;
 }
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index dfb25fd..e24a058 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -574,6 +574,7 @@ nfattr_failure:
 
 #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
 
+/*
 static struct nf_loginfo default_loginfo = {
 	.type =		NF_LOG_TYPE_ULOG,
 	.u = {
@@ -584,6 +585,7 @@ static struct nf_loginfo default_loginfo
 		},
 	},
 };
+*/
 
 /* log handler for internal netfilter logging api */
 static void
@@ -601,17 +603,17 @@ nfulnl_log_packet(unsigned int pf,
 	unsigned int qthreshold;
 	unsigned int nlbufsiz;
 
-	if (li_user && li_user->type == NF_LOG_TYPE_ULOG) 
+	if (li_user && (li_user->backends & NF_LOG_BACKEND_NFLOG)) 
 		li = li_user;
-	else
-		li = &default_loginfo;
+	else /* This packet  is none of our buisness */
+		return; 
 
-	inst = instance_lookup_get(li->u.ulog.group);
+	inst = instance_lookup_get(li->group);
 	if (!inst)
 		inst = instance_lookup_get(0);
 	if (!inst) {
 		PRINTR("nfnetlink_log: trying to log packet, "
-			"but no instance for group %u\n", li->u.ulog.group);
+			"but no instance for group %u\n", li->group);
 		return;
 	}
 
@@ -644,8 +646,8 @@ nfulnl_log_packet(unsigned int pf,
 
 	qthreshold = inst->qthreshold;
 	/* per-rule qthreshold overrides per-instance */
-	if (qthreshold > li->u.ulog.qthreshold)
-		qthreshold = li->u.ulog.qthreshold;
+	if (qthreshold > li->qthreshold)
+		qthreshold = li->qthreshold;
 	
 	switch (inst->copy_mode) {
 	case NFULNL_COPY_META:
@@ -848,7 +850,7 @@ nfulnl_recv_config(struct sock *ctnl, st
 			UDEBUG("unregistering log handler for pf=%u\n", pf);
 			/* This is a bug and a feature.  We cannot unregister
 			 * other handlers, like nfnetlink_inst can */
-			nf_log_unregister_pf(pf);
+			nf_log_unregister_pf(pf, &nfulnl_logger);
 			break;
 		default:
 			ret = -EINVAL;
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
new file mode 100644
index 0000000..c33ae0f
--- /dev/null
+++ b/net/netfilter/xt_LOG.c
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ *
+ * 2006-03-04 Gregor Maier <greogr@majordomus.org>
+ * 	Unified logging. Use nf_log for everything. Create xt_LOG target
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.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/xt_LOG.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+MODULE_DESCRIPTION("[ip,ip6]_tables LOG module");
+MODULE_ALIAS("ipt_LOG");
+MODULE_ALIAS("ip6t_LOG");
+
+static struct xt_target ipt_LOG_reg;
+static struct xt_target ip6t_LOG_reg;
+
+static unsigned int
+xt_log_target(struct sk_buff **pskb,
+       const struct net_device *in,
+       const struct net_device *out,
+       unsigned int hooknum,
+       const struct xt_target *target,
+       const void *targinfo,
+       void *userinfo)
+{
+	const struct xt_log_info *loginfo = targinfo;
+	
+	struct nf_loginfo li;
+	li.backends = loginfo->backends;
+	li.group = loginfo->group;
+	li.level = loginfo->level;
+	li.logflags = loginfo->logflags;
+	li.qthreshold = 1;
+
+	if (target == &ipt_LOG_reg)
+		nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, loginfo->prefix);
+	else if (target == &ip6t_LOG_reg)
+		nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, loginfo->prefix);
+
+	return XT_CONTINUE;
+}
+
+
+static int xt_log_checkentry(const char *tablename,
+			      const void *e,
+					const struct xt_target *target,
+			      void *targinfo,
+			      unsigned int targinfosize,
+			      unsigned int hook_mask)
+{
+	const struct xt_log_info *loginfo = targinfo;
+
+
+	if (loginfo->level >= 8) {
+		printk(KERN_WARNING "LOG: level %u >= 8\n", loginfo->level);
+		return 0;
+	}
+	if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
+		printk(KERN_WARNING "LOG: prefix term %i\n",
+		       loginfo->prefix[sizeof(loginfo->prefix) - 1]);
+		return 0;
+	}
+	printk(KERN_WARNING "LOG: group setting is: %d\n", loginfo->group);
+	
+
+	
+	return 1;
+}
+
+static struct xt_target ipt_LOG_reg = {
+	.name		= "LOG",
+	.target		= xt_log_target,
+	.checkentry	= xt_log_checkentry,
+	.targetsize	= sizeof(struct xt_log_info),
+	.me		= THIS_MODULE,
+};
+
+static struct xt_target ip6t_LOG_reg = {
+	.name		= "LOG",
+	.target		= xt_log_target,
+	.checkentry	= xt_log_checkentry,
+	.targetsize	= sizeof(struct xt_log_info),
+	.me		= THIS_MODULE,
+};
+
+
+static int __init init(void)
+{
+	int ret;
+
+	printk(KERN_WARNING "LOG init called\n");
+	ret = xt_register_target(AF_INET, &ipt_LOG_reg);
+	if (ret)
+		return ret;
+	ret = xt_register_target(AF_INET6, &ip6t_LOG_reg);
+	if (ret)
+		goto out_ip;
+
+	printk(KERN_WARNING "LOG loaded\n");
+	return ret;
+
+out_ip:
+	xt_unregister_target(AF_INET, &ipt_LOG_reg);
+
+	return ret;
+}
+
+static void __exit fini(void)
+{
+	xt_unregister_target(AF_INET, &ipt_LOG_reg);
+	xt_unregister_target(AF_INET6, &ip6t_LOG_reg);
+}
+
+module_init(init);
+module_exit(fini);

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-10 19:10 [RFC] [PATCH] clean up nf_log API Harald Welte
  2006-05-11  5:36 ` Gregor Maier
@ 2006-05-11  6:56 ` Patrick McHardy
  2006-05-11  8:25   ` Harald Welte
  2006-05-11  8:54 ` Holger Eitzenberger
  2 siblings, 1 reply; 11+ messages in thread
From: Patrick McHardy @ 2006-05-11  6:56 UTC (permalink / raw)
  To: Harald Welte; +Cc: Netfilter Development Mailinglist

Harald Welte wrote:
> Hi!
> 
> After spending some more time with the nf_log API, I think it still
> needs some further cleanup.
> 
> The main point of nf_log was to get some unfied support for packet
> logging backends, independent of the ruleset.  We currently have logging
> backend functionality tied to ipt_LOG, ipt_ULOG packet filter rules,
> which is inflexible and unsuitable for other entities within netfilter
> that want to log packets.
> 
> However, on thing that I missed during the nf_log implementation was the
> fact that it was no longer possible to have some rules using LOG, some
> others ULOG.  With the introduction of nf_log, it was only possible to
> use only one logging mechanism at any given point in time.
> 
> Also, there was no fallback support.  If you had configured
> nfnetlink_log as your backend and the admin decides to remove that
> module, nothing will be logged, even though other mechanisms might be
> available and present in the kernel.
> 
> Another problem was that neither the ULOG nor the LOG target supported
> all of the arguments/parameters that the nfnetlink_log backend needed.
> Therefore, it is practically impossible to exploit all the features 
> with the current kernel.
> 
> Therefore, I now propose the following patchset, which
> 
> 1) enhances 'struct nf_logger' with a list_head, usage counter a
>    priority and pf field
> 2) cleans up the api.  we now call nf_log_[un]register() once from every
>    backend.  registering doesn't mean that it's actually active.
>    successive calls to nf_log_[un]bind_pf() will actually bind a given
>    backend to the specified protocol family.
> 3) introduction of a new NFLOG target.  Only that NFLOG target supports
>    all the arguments that all our backends support.
> 4) Adds 'fallback' support.  This means that during unbind or
>    unregistration of a given backend, we check in the global list of
>    logging backends and chose the one with the hightest priority that
>    supports our protocol family.
> 4) modify ipt_LOG, ipt_ULOG, ip6t_LOG and nfnetlink_log to reflect the
>    abovementioned changes.

That all sounds very reasonable. How is the priority of a backend
determined?


> I have implemented the NFLOG target as iptables target (not xtables) due
> to 'customer need'.  However, once we decide that this patch should be
> merged, I'll provide an x_tables version.
> 
> There are some open questions:
> 
> a) we only search for 'fallback' backends during unregistration/unbind.
>    Should we also do this during registration?  Or whenever we receive
>    a packet and don't have a backend?  Early registration might become
>    problematic, since we don't really know what the user wants...


I think after each change we should just search for the highest priority
backend and use that.

> b) reference counting.  We could actually get_module / put_module the
>    module that implements a specific backend rather than using our own
>    use counter.

I guess it depends on whether we want to block unloading while it is
in use or do automatic fallback. I tend to prefer the later.

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-11  6:56 ` Patrick McHardy
@ 2006-05-11  8:25   ` Harald Welte
  2006-05-11  8:39     ` Patrick McHardy
  2006-05-11  8:58     ` Philip Craig
  0 siblings, 2 replies; 11+ messages in thread
From: Harald Welte @ 2006-05-11  8:25 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Netfilter Development Mailinglist

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

On Thu, May 11, 2006 at 08:56:49AM +0200, Patrick McHardy wrote:

> That all sounds very reasonable. How is the priority of a backend
> determined?

statically.  nfnetlink_log overrules ULOG, which overrules LOG.

We could make that configurable, but I think that's too much
flexibility.  If a user _wants_ a specific backend, he can chose it. if
not, we'll fallback on something.

> > a) we only search for 'fallback' backends during unregistration/unbind.
> >    Should we also do this during registration?  Or whenever we receive
> >    a packet and don't have a backend?  Early registration might become
> >    problematic, since we don't really know what the user wants...
> 
> I think after each change we should just search for the highest priority
> backend and use that.

ok, that's what the code does now.

> > b) reference counting.  We could actually get_module / put_module the
> >    module that implements a specific backend rather than using our own
> >    use counter.
> 
> I guess it depends on whether we want to block unloading while it is
> in use or do automatic fallback. I tend to prefer the later.

I agree, I prefer automatic fallback while giving the user the ability
to unload.  However, if people automatically unload 'unused' modules,
then there might be a problem (however, for both ULOG and nfnetlink_log,
userspace listeners would increment the refcount, I think).

Also, there is another unresolved problem:  What if we actually have
e.g. nfnetlink_log loaded, but it is unable to send a specific packet to
userspace because there is no listener for this Address family or log
group?   Should we then also fall back on some other backend?

At the moment we only fall back if a backend is unbound, but not if it
e.g. returns an error code because it was unable to log a specific
packet.

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-11  5:36 ` Gregor Maier
@ 2006-05-11  8:39   ` Harald Welte
  2006-05-11  8:44     ` Patrick McHardy
  0 siblings, 1 reply; 11+ messages in thread
From: Harald Welte @ 2006-05-11  8:39 UTC (permalink / raw)
  To: Gregor Maier; +Cc: Netfilter Development Mailinglist, Patrick McHardy

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

On Thu, May 11, 2006 at 05:36:36PM +1200, Gregor Maier wrote:
> Hi,
> 
> I wrote a patch about 2 month ago, that does something similiar.

mh, I must have missed that, sorry.

> Maybe some of it is usefull. If you are interested I would venture to
> update the patch.

I think we should merge them in some way.

> The patch uses only a modified version of the normal LOG target, but I
> wanted to change this to a NF_LOG target anyway.

Ok, a new LOG target would be fine, yes.

I now actually like the idea that the old LOG target and old ULOG target
just continue to do what the used to do. 

Only NFLOG supersedes all of them, and allows to access the full
flexibility of all backends.

> * Everything uses nf_log.c as logging API (excpect the obsolete ULOG targets)

as indicated, maybe we should modify LOG back to the old syslog-only
behaviour, too.

> * Loggers in nf_log.c are stackable. More than one logger can be registered
>     per PF

I don't like that idea, since it is overkill from my point of view.  If
somebody wants to log a packet twice, he can have multiple rules in the
ruleset for doing so.

> * nf_loginfo struct has been changed. Instead of the type field and the
>     union there is a "backends" field now that contains a bitmask specifing
>     which backends should process/log this packet. 

bitmask is only required if we go for multiple backends.

> * ipt_LOGc and ip6t_LOG.c have been splitted: 
>     * xt_LOG.c  now contains the targets. The targets
>         always use nf_log for logging. These should be the only
>         logging targets. They take care of setting up nf_loginfo for
>         logging to syslog and/or to other backends
>     * ip_log_syslog.c and ip6_log_syslog.c are new and contain the
>         syslog log backends. When these modules are loaded, the syslog
>         backend is registered with nf_log

that makes sense to a certain degree.  However, if we say that LOG
should be just like in old times, and we have a new NFLOG target, then
that change makes a little bit less sense.  Still I like it because it's
clean.

However, we need to make sure that module autoloading works, e.g. if
somebody uses your xt_LOG (or the 'LOG as in old times' target), then
the ip*_log_syslog.ko backend would have to be loaded on demand.  Also,
I'd prefer the names to indicate that they're netfilter related.

> POTENTIAL PROBLEMS / ALTERNATIVE SOLUTION
> * ipt_log_info and ip6t_log_info have been replaced by xt_log_info (which
>     has changed in size). This means iptables must be recompiled and older
>     iptables versions won't work with these changes. 

this is not acceptable.

I'll modify my patch and merge the changes of your patch that I like and
produce a resulting patchset later today.

Thansk!
-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-11  8:25   ` Harald Welte
@ 2006-05-11  8:39     ` Patrick McHardy
  2006-05-11  8:58     ` Philip Craig
  1 sibling, 0 replies; 11+ messages in thread
From: Patrick McHardy @ 2006-05-11  8:39 UTC (permalink / raw)
  To: Harald Welte; +Cc: Netfilter Development Mailinglist

Harald Welte wrote:
> On Thu, May 11, 2006 at 08:56:49AM +0200, Patrick McHardy wrote:
> 
> 
>>That all sounds very reasonable. How is the priority of a backend
>>determined?
> 
> 
> statically.  nfnetlink_log overrules ULOG, which overrules LOG.
> 
> We could make that configurable, but I think that's too much
> flexibility.  If a user _wants_ a specific backend, he can chose it. if
> not, we'll fallback on something.


I'm not sure about this. I assume a user would choose the backend
by specifying extra arguments to the NFLOG target, but that isn't
possible for internal logging.

>>>b) reference counting.  We could actually get_module / put_module the
>>>   module that implements a specific backend rather than using our own
>>>   use counter.
>>
>>I guess it depends on whether we want to block unloading while it is
>>in use or do automatic fallback. I tend to prefer the later.
> 
> 
> I agree, I prefer automatic fallback while giving the user the ability
> to unload.  However, if people automatically unload 'unused' modules,
> then there might be a problem (however, for both ULOG and nfnetlink_log,
> userspace listeners would increment the refcount, I think).


Do people still do that? I think distributions stopped the
"rmmod -something" triggered by cron a long time ago.
Anyway, netlink listeners will keep the module pinned.


> Also, there is another unresolved problem:  What if we actually have
> e.g. nfnetlink_log loaded, but it is unable to send a specific packet to
> userspace because there is no listener for this Address family or log
> group?   Should we then also fall back on some other backend?
> 
> At the moment we only fall back if a backend is unbound, but not if it
> e.g. returns an error code because it was unable to log a specific
> packet.


If the user explicitly specifies the backend we shouldn't fall back.
Otherwise I'm not sure .. it probably makes sense as long as we don't
permanently disable the higher priority backend.

BTW, I have a patch queued for 2.6.18 that makes the logging functions
return a status. I guess your patch already includes that, shall
I drop my patch?

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-11  8:39   ` Harald Welte
@ 2006-05-11  8:44     ` Patrick McHardy
  2006-05-11  8:59       ` Holger Eitzenberger
  0 siblings, 1 reply; 11+ messages in thread
From: Patrick McHardy @ 2006-05-11  8:44 UTC (permalink / raw)
  To: Harald Welte; +Cc: Gregor Maier, Netfilter Development Mailinglist

Harald Welte wrote:
> I now actually like the idea that the old LOG target and old ULOG target
> just continue to do what the used to do. 


I fully agree. I already changed the default behaviour back to just use
their own logging functions, nf_log backends can be used by specifying
an extra flag. This isn't supported by userspace so far, so we are free
to rip it out again.

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-10 19:10 [RFC] [PATCH] clean up nf_log API Harald Welte
  2006-05-11  5:36 ` Gregor Maier
  2006-05-11  6:56 ` Patrick McHardy
@ 2006-05-11  8:54 ` Holger Eitzenberger
  2 siblings, 0 replies; 11+ messages in thread
From: Holger Eitzenberger @ 2006-05-11  8:54 UTC (permalink / raw)
  To: Harald Welte; +Cc: Netfilter Development Mailinglist, Patrick McHardy

Harald Welte wrote:

> b) reference counting.  We could actually get_module / put_module the
>    module that implements a specific backend rather than using our own
>    use counter.

Yes, I saw this during nfnetlink_log evaluation.  It is kind of 
confusing if the module refcount stays zero all the time.

/holger


-- 
Holger Eitzenberger <heitzenberger@astaro.com> | Kernel Developer
Astaro AG | www.astaro.com | Phone +49-721-25516-246 | Fax -200

Astaro Security Linux
- PC Magazine Best of the Year 2004/2005
- CRN Best of the Year 2005
- SC Magazine "Best Buy" & 5 star rating - October 2005, Best of the 
Year 2005
- Internet Professionell "Empfehlung der Redaktion" - November 2005

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-11  8:25   ` Harald Welte
  2006-05-11  8:39     ` Patrick McHardy
@ 2006-05-11  8:58     ` Philip Craig
  1 sibling, 0 replies; 11+ messages in thread
From: Philip Craig @ 2006-05-11  8:58 UTC (permalink / raw)
  To: Harald Welte; +Cc: Netfilter Development Mailinglist, Patrick McHardy

On 05/11/2006 06:25 PM, Harald Welte wrote:
> I agree, I prefer automatic fallback while giving the user the ability
> to unload.  However, if people automatically unload 'unused' modules,
> then there might be a problem (however, for both ULOG and nfnetlink_log,
> userspace listeners would increment the refcount, I think).

What constitutes in use?  If a backend is in use whenever it is
the highest priority backend, then blocking unloading would mean
nfnetlink_log can never be unloaded.  Letting the user choose the
highest priority backend would solve that.  In which case I think
blocking unloading is desirable, we shouldn't unload the backend
the user has chosen.

And I assume that log rules can also specify a backend? (eg the
LOG and ULOG rules always will)  That should probably block
unloading too.

> Also, there is another unresolved problem:  What if we actually have
> e.g. nfnetlink_log loaded, but it is unable to send a specific packet to
> userspace because there is no listener for this Address family or log
> group?   Should we then also fall back on some other backend?

Just doing a printk to notify of the error is enough?
We probably should be doing a printk anyway if it is
a backend the user has chosen explicitly.

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-11  8:44     ` Patrick McHardy
@ 2006-05-11  8:59       ` Holger Eitzenberger
  2006-05-11 11:55         ` Harald Welte
  0 siblings, 1 reply; 11+ messages in thread
From: Holger Eitzenberger @ 2006-05-11  8:59 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: Harald Welte, Gregor Maier, Netfilter Development Mailinglist

Patrick McHardy wrote:

>>I now actually like the idea that the old LOG target and old ULOG target
>>just continue to do what the used to do. 

> I fully agree. I already changed the default behaviour back to just use
> their own logging functions, nf_log backends can be used by specifying
> an extra flag. This isn't supported by userspace so far, so we are free
> to rip it out again.

IMO this is the best solution too, since the current way is not very 
transparent to the user.  Worse than that, ULOG even is stamped 
"deprecated" in kconfig of 2.6.15.y, so most people will just be able 
use the limited arguments of the LOG target.

-- 
Holger Eitzenberger <heitzenberger@astaro.com> | Kernel Developer
Astaro AG | www.astaro.com | Phone +49-721-25516-246 | Fax -200

Astaro Security Linux
- PC Magazine Best of the Year 2004/2005
- CRN Best of the Year 2005
- SC Magazine "Best Buy" & 5 star rating - October 2005, Best of the 
Year 2005
- Internet Professionell "Empfehlung der Redaktion" - November 2005

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

* Re: [RFC] [PATCH] clean up nf_log API
  2006-05-11  8:59       ` Holger Eitzenberger
@ 2006-05-11 11:55         ` Harald Welte
  0 siblings, 0 replies; 11+ messages in thread
From: Harald Welte @ 2006-05-11 11:55 UTC (permalink / raw)
  To: Holger Eitzenberger
  Cc: Gregor Maier, Netfilter Development Mailinglist, Patrick McHardy

On Thu, May 11, 2006 at 10:59:12AM +0200, Holger Eitzenberger wrote:

> IMO this is the best solution too, since the current way is not very transparent to the user.  Worse 
> than that, ULOG even is stamped "deprecated" in kconfig of 2.6.15.y, so most people will just be able 
> use the limited arguments of the LOG target.

JFTI: that deprecated has been removed in more current mainline kernels.

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

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

end of thread, other threads:[~2006-05-11 11:55 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-10 19:10 [RFC] [PATCH] clean up nf_log API Harald Welte
2006-05-11  5:36 ` Gregor Maier
2006-05-11  8:39   ` Harald Welte
2006-05-11  8:44     ` Patrick McHardy
2006-05-11  8:59       ` Holger Eitzenberger
2006-05-11 11:55         ` Harald Welte
2006-05-11  6:56 ` Patrick McHardy
2006-05-11  8:25   ` Harald Welte
2006-05-11  8:39     ` Patrick McHardy
2006-05-11  8:58     ` Philip Craig
2006-05-11  8:54 ` Holger Eitzenberger

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