[PATCH][RFC] iptables patch for: Unifiy logging in netfilter using nf_log, take #1

Gregor Maier gregor at net.in.tum.de
Thu Mar 9 20:36:37 CET 2006


[PATCH][RFC] This patch adds support for the modified LOG targets
from the nf-log-unification patch. 

* Support for syslog and libnetfilter_log backend
* The nf-log backends can be combined (log to one
    backend, log to both, log to none)
* semantics of "old" LOG target are preserved


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

===================================================================
Index: include/linux/netfilter/xt_LOG.h
===================================================================
--- include/linux/netfilter/xt_LOG.h	(revision 0)
+++ include/linux/netfilter/xt_LOG.h	(revision 0)
@@ -0,0 +1,23 @@
+/* iptables module for logging / LOG target
+ *
+ * (C) 2006 Gregor Maier <gregor at majordomus.org>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ * 
+*/
+#ifndef _XT_LOG_TARGET_H
+#define _XT_LOG_TARGET_H
+
+/* This file intentionally left empty
+ *
+ * When the kernel doesn't provive xt_LOG.h this file will
+ * be included, so the preprocessor won't complain 
+ *
+ * In the "real" xt_LOG.h file XT_LOG_BACKEND_SYSLOG is defined
+ * and we use this to determine if the xt_LOG target is used
+ * or the ipt_LOG, ip6t_LOG targets 
+ *
+ * XXX: There must be a way to do this more nicely
+ */
+
+#endif /* _XT_LOG_TARGET_H */
Index: extensions/libip6t_LOG.c
===================================================================
--- extensions/libip6t_LOG.c	(revision 6554)
+++ extensions/libip6t_LOG.c	(working copy)
@@ -1,4 +1,4 @@
-/* Shared library add-on to iptables to add LOG support. */
+/* Shared library add-on to ip6tables to add LOG support. */
 #include <stdio.h>
 #include <netdb.h>
 #include <string.h>
@@ -6,35 +6,55 @@
 #include <syslog.h>
 #include <getopt.h>
 #include <ip6tables.h>
+/* xt_LOG.h is either from the kernel (then xt_LOG target is
+ * available) and XT_LOG_BACKEND_* are defined). Otherwise
+ * xt_LOG.h from the iptables include dir is used and XT_LOG_BACKEND_
+ * is not defined
+ */
+#include <linux/netfilter/xt_LOG.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
+
+#ifndef XT_LOG_BACKEND_SYSLOG   
 #include <linux/netfilter_ipv6/ip6t_LOG.h>
+#define xt_log_info ip6t_log_info
+#endif
+	
 
-#ifndef IP6T_LOG_UID	/* Old kernel */
-#define IP6T_LOG_UID	0x08
+#define LOG_DEFAULT_LEVEL LOG_WARNING
+
+#ifndef IP6T_LOG_UID /* Old kernel */
+#define IP6T_LOG_UID	0x08	/* Log UID owning local socket */
 #undef  IP6T_LOG_MASK
 #define IP6T_LOG_MASK	0x0f
 #endif
 
-#define LOG_DEFAULT_LEVEL LOG_WARNING
-
 /* Function which prints out usage message. */
 static void
 help(void)
 {
 	printf(
 "LOG v%s options:\n"
+" --log-prefix prefix		Prefix log messages with this prefix.\n"
+#ifdef XT_LOG_BACKEND_SYSLOG
+" --log-no-syslog		Do not use syslog backend for logging\n" 
+" --log-group group		Log to nf_netlink_log group group (0 - 65535)\n" 
+" Options when using syslog backend:\n"
+#endif
 " --log-level level		Level of logging (numeric or see syslog.conf)\n"
-" --log-prefix prefix		Prefix log messages with this prefix.\n\n"
-" --log-tcp-sequence		Log TCP sequence numbers.\n\n"
-" --log-tcp-options		Log TCP options.\n\n"
-" --log-ip-options		Log IP options.\n\n"
+" --log-tcp-sequence		Log TCP sequence numbers.\n"
+" --log-tcp-options		Log TCP options.\n"
+" --log-ip-options		Log IP options.\n"
 " --log-uid			Log UID owning the local socket.\n\n",
 IPTABLES_VERSION);
 }
 
 static struct option opts[] = {
+	{ .name = "log-prefix",       .has_arg = 1, .flag = 0, .val = '#' },
+#ifdef XT_LOG_BACKEND_SYSLOG
+	{ .name = "log-no-syslog",    .has_arg = 0, .flag = 0, .val = 's' },
+	{ .name = "log-group",        .has_arg = 1, .flag = 0, .val = 'g' },
+#endif
 	{ .name = "log-level",        .has_arg = 1, .flag = 0, .val = '!' },
-	{ .name = "log-prefix",       .has_arg = 1, .flag = 0, .val = '#' },
 	{ .name = "log-tcp-sequence", .has_arg = 0, .flag = 0, .val = '1' },
 	{ .name = "log-tcp-options",  .has_arg = 0, .flag = 0, .val = '2' },
 	{ .name = "log-ip-options",   .has_arg = 0, .flag = 0, .val = '3' },
@@ -46,8 +66,11 @@
 static void
 init(struct ip6t_entry_target *t, unsigned int *nfcache)
 {
-	struct ip6t_log_info *loginfo = (struct ip6t_log_info *)t->data;
+	struct xt_log_info *loginfo = (struct xt_log_info *)t->data;
 
+#ifdef XT_LOG_BACKEND_SYSLOG
+	loginfo->backends = XT_LOG_BACKEND_SYSLOG;
+#endif
 	loginfo->level = LOG_DEFAULT_LEVEL;
 
 }
@@ -105,6 +128,11 @@
 #define IP6T_LOG_OPT_TCPOPT 0x08
 #define IP6T_LOG_OPT_IPOPT 0x10
 #define IP6T_LOG_OPT_UID 0x20
+/* We don't ifdef those, since they don't hurt. And we can use them in parse to
+ * save tons of ifdefs */
+#define IP6T_LOG_OPT_SYSLOG_MASK (IP6T_LOG_OPT_LEVEL | IP6T_LOG_OPT_TCPSEQ | IP6T_LOG_OPT_TCPOPT | IP6T_LOG_OPT_IPOPT | IP6T_LOG_OPT_UID)
+#define IP6T_LOG_OPT_NO_SYSLOG 0x40
+#define IP6T_LOG_OPT_GROUP 0x80
 
 /* Function which parses command options; returns true if it
    ate an option */
@@ -113,10 +141,45 @@
       const struct ip6t_entry *entry,
       struct ip6t_entry_target **target)
 {
-	struct ip6t_log_info *loginfo = (struct ip6t_log_info *)(*target)->data;
+	struct xt_log_info *loginfo = (struct xt_log_info *)(*target)->data;
 
 	switch (c) {
+#ifdef XT_LOG_BACKEND_SYSLOG  /* kernel with stackable loggers */
+		unsigned group;
+	case 's':
+		if (*flags & IP6T_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-no-syslog twice");
+
+		/* check if any of the syslog related opts has been specified */
+		if (*flags & IP6T_LOG_OPT_SYSLOG_MASK)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-no-syslog when using syslog only options");
+		loginfo->backends &= (~XT_LOG_BACKEND_SYSLOG);
+		*flags |= IP6T_LOG_OPT_NO_SYSLOG;
+		break;
+
+	case 'g':
+		if (*flags & IP6T_LOG_OPT_GROUP)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-group twice");
+		if (check_inverse(optarg, &invert, NULL, 0))
+			exit_error(PARAMETER_PROBLEM,
+				   "Unexpected `!' after --log-group");
+		if (string_to_number(optarg, 0, 65535, &group) < 0)
+			exit_error(PARAMETER_PROBLEM,
+				   "--log-group has to be between 0 and 65535");
+		loginfo->group = group;
+		loginfo->backends |= XT_LOG_BACKEND_NFLOG;
+		*flags |= IP6T_LOG_OPT_GROUP;
+		break;
+#endif
+/* We can savely check for IP6T_LOG_OPT_NO_SYSLOG without the need for ifdefs */
 	case '!':
+		if (*flags & IP6T_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-level when not logging to syslog");
+
 		if (*flags & IP6T_LOG_OPT_LEVEL)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-level twice");
@@ -152,6 +215,10 @@
 		break;
 
 	case '1':
+		if (*flags & IP6T_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-tcp-sequence when not logging to syslog");
+
 		if (*flags & IP6T_LOG_OPT_TCPSEQ)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-tcp-sequence "
@@ -162,6 +229,10 @@
 		break;
 
 	case '2':
+		if (*flags & IP6T_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-tcp-options when not logging to syslog");
+
 		if (*flags & IP6T_LOG_OPT_TCPOPT)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-tcp-options twice");
@@ -171,6 +242,10 @@
 		break;
 
 	case '3':
+		if (*flags & IP6T_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-ip-options when not logging to syslog");
+
 		if (*flags & IP6T_LOG_OPT_IPOPT)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-ip-options twice");
@@ -180,10 +255,14 @@
 		break;
 
 	case '4':
+		if (*flags & IP6T_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-uid when not logging to syslog");
+
 		if (*flags & IP6T_LOG_OPT_UID)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-uid twice");
-
+		
 		loginfo->logflags |= IP6T_LOG_UID;
 		*flags |= IP6T_LOG_OPT_UID;
 		break;
@@ -206,35 +285,63 @@
       const struct ip6t_entry_target *target,
       int numeric)
 {
-	const struct ip6t_log_info *loginfo
-		= (const struct ip6t_log_info *)target->data;
+	const struct xt_log_info *loginfo
+		= (const struct xt_log_info *)target->data;
 	unsigned int i = 0;
+	/* These flag saves some ifdefs and thus make the code more readable */
+	int use_syslog = 1; /* is uselog used as backend ? */
 
+#ifdef XT_LOG_BACKEND_SYSLOG
+		if (!(loginfo->backends & XT_LOG_BACKEND_SYSLOG))
+			use_syslog = 0;
+#endif
+
 	printf("LOG ");
-	if (numeric)
-		printf("flags %u level %u ",
-		       loginfo->logflags, loginfo->level);
+	if (numeric) {
+#ifdef XT_LOG_BACKEND_SYSLOG
+		if (loginfo->backends & XT_LOG_BACKEND_NFLOG)
+			printf("group %u ", loginfo->group);
+#endif
+
+		if (!use_syslog)
+			printf("no-syslog ");
+		else 
+			printf("flags %u level %u ",
+			       loginfo->logflags, loginfo->level);
+	}
 	else {
-		for (i = 0;
-		     i < sizeof(ip6t_log_names) / sizeof(struct ip6t_log_names);
-		     i++) {
-			if (loginfo->level == ip6t_log_names[i].level) {
-				printf("level %s ", ip6t_log_names[i].name);
-				break;
+		if (use_syslog) {
+			for (i = 0;
+			     i < sizeof(ip6t_log_names) / sizeof(struct ip6t_log_names);
+			     i++) {
+				if (loginfo->level == ip6t_log_names[i].level) {
+					printf("level %s ", ip6t_log_names[i].name);
+					break;
+				}
 			}
 		}
-		if (i == sizeof(ip6t_log_names) / sizeof(struct ip6t_log_names))
-			printf("UNKNOWN level %u ", loginfo->level);
-		if (loginfo->logflags & IP6T_LOG_TCPSEQ)
-			printf("tcp-sequence ");
-		if (loginfo->logflags & IP6T_LOG_TCPOPT)
-			printf("tcp-options ");
-		if (loginfo->logflags & IP6T_LOG_IPOPT)
-			printf("ip-options ");
-		if (loginfo->logflags & IP6T_LOG_UID)
-			printf("uid ");
-		if (loginfo->logflags & ~(IP6T_LOG_MASK))
-			printf("unknown-flags ");
+
+#ifdef XT_LOG_BACKEND_SYSLOG
+		if (loginfo->backends & XT_LOG_BACKEND_NFLOG)
+			printf("group %u ", loginfo->group);
+#endif
+		if (!use_syslog) {
+			printf("no-syslog ");
+		}
+		else {
+			if (i == sizeof(ip6t_log_names) / sizeof(struct ip6t_log_names))
+				printf("UNKNOWN level %u ", loginfo->level);
+			if (loginfo->logflags & IP6T_LOG_TCPSEQ)
+				printf("tcp-sequence ");
+			if (loginfo->logflags & IP6T_LOG_TCPOPT)
+				printf("tcp-options ");
+			if (loginfo->logflags & IP6T_LOG_IPOPT)
+				printf("ip-options ");
+			if (loginfo->logflags & IP6T_LOG_UID)
+				printf("uid ");
+			if (loginfo->logflags & ~(IP6T_LOG_MASK))
+				printf("unknown-flags ");
+		}
 	}
 
 	if (strcmp(loginfo->prefix, "") != 0)
@@ -245,14 +352,21 @@
 static void
 save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
 {
-	const struct ip6t_log_info *loginfo
-		= (const struct ip6t_log_info *)target->data;
-
+	const struct xt_log_info *loginfo
+		= (const struct xt_log_info *)target->data;
+#ifdef XT_LOG_BACKEND_SYSLOG
+	if (loginfo->backends & XT_LOG_BACKEND_NFLOG)
+		printf("--log-group %u ", loginfo->group);
+	if (!(loginfo->backends & XT_LOG_BACKEND_SYSLOG))
+		printf("--log-no-syslog ");
+#endif
+	/* Don't need to check for no-syslog, since the options won't be set if
+	 * not logging to syslog */
 	if (strcmp(loginfo->prefix, "") != 0)
 		printf("--log-prefix \"%s\" ", loginfo->prefix);
 
 	if (loginfo->level != LOG_DEFAULT_LEVEL)
-		printf("--log-level %d ", loginfo->level);
+		printf("--log-level %u ", loginfo->level);
 
 	if (loginfo->logflags & IP6T_LOG_TCPSEQ)
 		printf("--log-tcp-sequence ");
@@ -269,8 +383,9 @@
 = {
     .name          = "LOG",
     .version       = IPTABLES_VERSION,
-    .size          = IP6T_ALIGN(sizeof(struct ip6t_log_info)),
-    .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_log_info)),
+/* IP6T_ALIGN is defined as XT_ALIGN if available */
+    .size          = IP6T_ALIGN(sizeof(struct xt_log_info)), 
+    .userspacesize = IP6T_ALIGN(sizeof(struct xt_log_info)),
     .help          = &help,
     .init          = &init,
     .parse         = &parse,
Index: extensions/libip6t_LOG.man
===================================================================
--- extensions/libip6t_LOG.man	(revision 6554)
+++ extensions/libip6t_LOG.man	(working copy)
@@ -1,22 +1,39 @@
 Turn on kernel logging of matching packets.  When this option is set
-for a rule, the Linux kernel will print some information on all
-matching packets (like most IPv6 IPv6-header fields) via the kernel log
-(where it can be read with
+for a rule, the Linux kernel logs this packet to all specified logging
+backends. There is a syslog backend, which prints some 
+information on matching packets (like most IPv6 header fields) via the
+kernel log (where it can be read with
 .I dmesg
 or 
 .IR syslogd (8)).
-This is a "non-terminating target", i.e. rule traversal continues at
-the next rule.  So if you want to LOG the packets you refuse, use two
-separate rules with the same matching criteria, first using target LOG
-then DROP (or REJECT).
+The other backend is nfnetlink_log, which passes 
+packets to userspace to be handled there. Userspace processes my
+subsribe to various log groups and receive the packets. A packet can be
+logged to any number of backends. Default is to log only to the syslog 
+backend. 
+This is a "non-terminating target", i.e. rule traversal 
+continues at the next rule.  So if you want to LOG the packets you 
+refuse, use two separate rules with the same matching criteria, first
+using target LOG then DROP (or REJECT).
 .TP
-.BI "--log-level " "level"
-Level of logging (numeric or see \fIsyslog.conf\fP(5)).
-.TP
 .BI "--log-prefix " "prefix"
 Prefix log messages with the specified prefix; up to 29 letters long,
 and useful for distinguishing messages in the logs.
 .TP
+.B --log-no-syslog
+Do not log to syslog backend. 
+.TP
+.B Options for nfnetlink_log backend
+.TP
+.BI "--log-group " "group"
+Log this packet to nfnetlink_log backend. Group specifies the log group for
+this target.
+.TP
+.B Options for syslog backend
+.TP
+.BI "--log-level " "level"
+Level of logging (numeric or see \fIsyslog.conf\fP(5)).
+.TP
 .B --log-tcp-sequence
 Log TCP sequence numbers. This is a security risk if the log is
 readable by users.
Index: extensions/libipt_LOG.c
===================================================================
--- extensions/libipt_LOG.c	(revision 6554)
+++ extensions/libipt_LOG.c	(working copy)
@@ -6,8 +6,19 @@
 #include <syslog.h>
 #include <getopt.h>
 #include <iptables.h>
+/* xt_LOG.h is either from the kernel (then xt_LOG target is
+ * available) and XT_LOG_BACKEND_* are defined). Otherwise
+ * xt_LOG.h from the iptables include dir is used and XT_LOG_BACKEND_
+ * is not defined
+ */
+#include <linux/netfilter/xt_LOG.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
+
+#ifndef XT_LOG_BACKEND_SYSLOG   
 #include <linux/netfilter_ipv4/ipt_LOG.h>
+#define xt_log_info ipt_log_info
+#endif
+	
 
 #define LOG_DEFAULT_LEVEL LOG_WARNING
 
@@ -23,18 +34,27 @@
 {
 	printf(
 "LOG v%s options:\n"
+" --log-prefix prefix		Prefix log messages with this prefix.\n"
+#ifdef XT_LOG_BACKEND_SYSLOG
+" --log-no-syslog		Do not use syslog backend for logging\n" 
+" --log-group group		Log to nf_netlink_log group group (0 - 65535)\n" 
+" Options when using syslog backend:\n"
+#endif
 " --log-level level		Level of logging (numeric or see syslog.conf)\n"
-" --log-prefix prefix		Prefix log messages with this prefix.\n\n"
-" --log-tcp-sequence		Log TCP sequence numbers.\n\n"
-" --log-tcp-options		Log TCP options.\n\n"
-" --log-ip-options		Log IP options.\n\n"
+" --log-tcp-sequence		Log TCP sequence numbers.\n"
+" --log-tcp-options		Log TCP options.\n"
+" --log-ip-options		Log IP options.\n"
 " --log-uid			Log UID owning the local socket.\n\n",
 IPTABLES_VERSION);
 }
 
 static struct option opts[] = {
+	{ .name = "log-prefix",       .has_arg = 1, .flag = 0, .val = '#' },
+#ifdef XT_LOG_BACKEND_SYSLOG
+	{ .name = "log-no-syslog",    .has_arg = 0, .flag = 0, .val = 's' },
+	{ .name = "log-group",        .has_arg = 1, .flag = 0, .val = 'g' },
+#endif
 	{ .name = "log-level",        .has_arg = 1, .flag = 0, .val = '!' },
-	{ .name = "log-prefix",       .has_arg = 1, .flag = 0, .val = '#' },
 	{ .name = "log-tcp-sequence", .has_arg = 0, .flag = 0, .val = '1' },
 	{ .name = "log-tcp-options",  .has_arg = 0, .flag = 0, .val = '2' },
 	{ .name = "log-ip-options",   .has_arg = 0, .flag = 0, .val = '3' },
@@ -46,8 +66,11 @@
 static void
 init(struct ipt_entry_target *t, unsigned int *nfcache)
 {
-	struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data;
+	struct xt_log_info *loginfo = (struct xt_log_info *)t->data;
 
+#ifdef XT_LOG_BACKEND_SYSLOG
+	loginfo->backends = XT_LOG_BACKEND_SYSLOG;
+#endif
 	loginfo->level = LOG_DEFAULT_LEVEL;
 
 }
@@ -105,6 +128,11 @@
 #define IPT_LOG_OPT_TCPOPT 0x08
 #define IPT_LOG_OPT_IPOPT 0x10
 #define IPT_LOG_OPT_UID 0x20
+/* We don't ifdef those, since they don't hurt. And we can use them in parse to
+ * save tons of ifdefs */
+#define IPT_LOG_OPT_SYSLOG_MASK (IPT_LOG_OPT_LEVEL | IPT_LOG_OPT_TCPSEQ | IPT_LOG_OPT_TCPOPT | IPT_LOG_OPT_IPOPT | IPT_LOG_OPT_UID)
+#define IPT_LOG_OPT_NO_SYSLOG 0x40
+#define IPT_LOG_OPT_GROUP 0x80
 
 /* Function which parses command options; returns true if it
    ate an option */
@@ -113,10 +141,45 @@
       const struct ipt_entry *entry,
       struct ipt_entry_target **target)
 {
-	struct ipt_log_info *loginfo = (struct ipt_log_info *)(*target)->data;
+	struct xt_log_info *loginfo = (struct xt_log_info *)(*target)->data;
 
 	switch (c) {
+#ifdef XT_LOG_BACKEND_SYSLOG  /* kernel with stackable loggers */
+		unsigned group;
+	case 's':
+		if (*flags & IPT_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-no-syslog twice");
+
+		/* check if any of the syslog related opts has been specified */
+		if (*flags & IPT_LOG_OPT_SYSLOG_MASK)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-no-syslog when using syslog only options");
+		loginfo->backends &= (~XT_LOG_BACKEND_SYSLOG);
+		*flags |= IPT_LOG_OPT_NO_SYSLOG;
+		break;
+
+	case 'g':
+		if (*flags & IPT_LOG_OPT_GROUP)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-group twice");
+		if (check_inverse(optarg, &invert, NULL, 0))
+			exit_error(PARAMETER_PROBLEM,
+				   "Unexpected `!' after --log-group");
+		if (string_to_number(optarg, 0, 65535, &group) < 0)
+			exit_error(PARAMETER_PROBLEM,
+				   "--log-group has to be between 0 and 65535");
+		loginfo->group = group;
+		loginfo->backends |= XT_LOG_BACKEND_NFLOG;
+		*flags |= IPT_LOG_OPT_GROUP;
+		break;
+#endif
+/* We can savely check for IPT_LOG_OPT_NO_SYSLOG without the need for ifdefs */
 	case '!':
+		if (*flags & IPT_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-level when not logging to syslog");
+
 		if (*flags & IPT_LOG_OPT_LEVEL)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-level twice");
@@ -152,6 +215,10 @@
 		break;
 
 	case '1':
+		if (*flags & IPT_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-tcp-sequence when not logging to syslog");
+
 		if (*flags & IPT_LOG_OPT_TCPSEQ)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-tcp-sequence "
@@ -162,6 +229,10 @@
 		break;
 
 	case '2':
+		if (*flags & IPT_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-tcp-options when not logging to syslog");
+
 		if (*flags & IPT_LOG_OPT_TCPOPT)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-tcp-options twice");
@@ -171,6 +242,10 @@
 		break;
 
 	case '3':
+		if (*flags & IPT_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-ip-options when not logging to syslog");
+
 		if (*flags & IPT_LOG_OPT_IPOPT)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-ip-options twice");
@@ -180,10 +255,14 @@
 		break;
 
 	case '4':
+		if (*flags & IPT_LOG_OPT_NO_SYSLOG)
+			exit_error(PARAMETER_PROBLEM,
+				   "Can't specify --log-uid when not logging to syslog");
+
 		if (*flags & IPT_LOG_OPT_UID)
 			exit_error(PARAMETER_PROBLEM,
 				   "Can't specify --log-uid twice");
-
+		
 		loginfo->logflags |= IPT_LOG_UID;
 		*flags |= IPT_LOG_OPT_UID;
 		break;
@@ -206,35 +285,63 @@
       const struct ipt_entry_target *target,
       int numeric)
 {
-	const struct ipt_log_info *loginfo
-		= (const struct ipt_log_info *)target->data;
+	const struct xt_log_info *loginfo
+		= (const struct xt_log_info *)target->data;
 	unsigned int i = 0;
+	/* These flag saves some ifdefs and thus make the code more readable */
+	int use_syslog = 1; /* is uselog used as backend ? */
 
+#ifdef XT_LOG_BACKEND_SYSLOG
+		if (!(loginfo->backends & XT_LOG_BACKEND_SYSLOG))
+			use_syslog = 0;
+#endif
+
 	printf("LOG ");
-	if (numeric)
-		printf("flags %u level %u ",
-		       loginfo->logflags, loginfo->level);
+	if (numeric) {
+#ifdef XT_LOG_BACKEND_SYSLOG
+		if (loginfo->backends & XT_LOG_BACKEND_NFLOG)
+			printf("group %u ", loginfo->group);
+#endif
+
+		if (!use_syslog)
+			printf("no-syslog ");
+		else 
+			printf("flags %u level %u ",
+			       loginfo->logflags, loginfo->level);
+	}
 	else {
-		for (i = 0;
-		     i < sizeof(ipt_log_names) / sizeof(struct ipt_log_names);
-		     i++) {
-			if (loginfo->level == ipt_log_names[i].level) {
-				printf("level %s ", ipt_log_names[i].name);
-				break;
+		if (use_syslog) {
+			for (i = 0;
+			     i < sizeof(ipt_log_names) / sizeof(struct ipt_log_names);
+			     i++) {
+				if (loginfo->level == ipt_log_names[i].level) {
+					printf("level %s ", ipt_log_names[i].name);
+					break;
+				}
 			}
 		}
-		if (i == sizeof(ipt_log_names) / sizeof(struct ipt_log_names))
-			printf("UNKNOWN level %u ", loginfo->level);
-		if (loginfo->logflags & IPT_LOG_TCPSEQ)
-			printf("tcp-sequence ");
-		if (loginfo->logflags & IPT_LOG_TCPOPT)
-			printf("tcp-options ");
-		if (loginfo->logflags & IPT_LOG_IPOPT)
-			printf("ip-options ");
-		if (loginfo->logflags & IPT_LOG_UID)
-			printf("uid ");
-		if (loginfo->logflags & ~(IPT_LOG_MASK))
-			printf("unknown-flags ");
+
+#ifdef XT_LOG_BACKEND_SYSLOG
+		if (loginfo->backends & XT_LOG_BACKEND_NFLOG)
+			printf("group %u ", loginfo->group);
+#endif
+		if (!use_syslog) {
+			printf("no-syslog ");
+		}
+		else {
+			if (i == sizeof(ipt_log_names) / sizeof(struct ipt_log_names))
+				printf("UNKNOWN level %u ", loginfo->level);
+			if (loginfo->logflags & IPT_LOG_TCPSEQ)
+				printf("tcp-sequence ");
+			if (loginfo->logflags & IPT_LOG_TCPOPT)
+				printf("tcp-options ");
+			if (loginfo->logflags & IPT_LOG_IPOPT)
+				printf("ip-options ");
+			if (loginfo->logflags & IPT_LOG_UID)
+				printf("uid ");
+			if (loginfo->logflags & ~(IPT_LOG_MASK))
+				printf("unknown-flags ");
+		}
 	}
 
 	if (strcmp(loginfo->prefix, "") != 0)
@@ -245,14 +352,21 @@
 static void
 save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
 {
-	const struct ipt_log_info *loginfo
-		= (const struct ipt_log_info *)target->data;
-
+	const struct xt_log_info *loginfo
+		= (const struct xt_log_info *)target->data;
+#ifdef XT_LOG_BACKEND_SYSLOG
+	if (loginfo->backends & XT_LOG_BACKEND_NFLOG)
+		printf("--log-group %u ", loginfo->group);
+	if (!(loginfo->backends & XT_LOG_BACKEND_SYSLOG))
+		printf("--log-no-syslog ");
+#endif
+	/* Don't need to check for no-syslog, since the options won't be set if
+	 * not logging to syslog */
 	if (strcmp(loginfo->prefix, "") != 0)
 		printf("--log-prefix \"%s\" ", loginfo->prefix);
 
 	if (loginfo->level != LOG_DEFAULT_LEVEL)
-		printf("--log-level %d ", loginfo->level);
+		printf("--log-level %u ", loginfo->level);
 
 	if (loginfo->logflags & IPT_LOG_TCPSEQ)
 		printf("--log-tcp-sequence ");
@@ -269,8 +383,9 @@
 = {
     .name          = "LOG",
     .version       = IPTABLES_VERSION,
-    .size          = IPT_ALIGN(sizeof(struct ipt_log_info)),
-    .userspacesize = IPT_ALIGN(sizeof(struct ipt_log_info)),
+/* IPT_ALIGN is defined as XT_ALIGN if available */
+    .size          = IPT_ALIGN(sizeof(struct xt_log_info)), 
+    .userspacesize = IPT_ALIGN(sizeof(struct xt_log_info)),
     .help          = &help,
     .init          = &init,
     .parse         = &parse,
Index: extensions/libipt_LOG.man
===================================================================
--- extensions/libipt_LOG.man	(revision 6554)
+++ extensions/libipt_LOG.man	(working copy)
@@ -1,22 +1,39 @@
 Turn on kernel logging of matching packets.  When this option is set
-for a rule, the Linux kernel will print some information on all
-matching packets (like most IP header fields) via the kernel log
-(where it can be read with
+for a rule, the Linux kernel logs this packet to all specified logging
+backends. There is a syslog backend, which prints some 
+information on matching packets (like most IP header fields) via the
+kernel log (where it can be read with
 .I dmesg
 or 
 .IR syslogd (8)).
-This is a "non-terminating target", i.e. rule traversal continues at
-the next rule.  So if you want to LOG the packets you refuse, use two
-separate rules with the same matching criteria, first using target LOG
-then DROP (or REJECT).
+The other backend is nfnetlink_log, which passes 
+packets to userspace to be handled there. Userspace processes my
+subsribe to various log groups and receive the packets. A packet can be
+logged to any number of backends. Default is to log only to the syslog 
+backend. 
+This is a "non-terminating target", i.e. rule traversal 
+continues at the next rule.  So if you want to LOG the packets you 
+refuse, use two separate rules with the same matching criteria, first
+using target LOG then DROP (or REJECT).
 .TP
-.BI "--log-level " "level"
-Level of logging (numeric or see \fIsyslog.conf\fP(5)).
-.TP
 .BI "--log-prefix " "prefix"
 Prefix log messages with the specified prefix; up to 29 letters long,
 and useful for distinguishing messages in the logs.
 .TP
+.B --log-no-syslog
+Do not log to syslog backend. 
+.TP
+.B Options for nfnetlink_log backend
+.TP
+.BI "--log-group " "group"
+Log this packet to nfnetlink_log backend. Group specifies the log group for
+this target.
+.TP
+.B Options for syslog backend
+.TP
+.BI "--log-level " "level"
+Level of logging (numeric or see \fIsyslog.conf\fP(5)).
+.TP
 .B --log-tcp-sequence
 Log TCP sequence numbers. This is a security risk if the log is
 readable by users.
Index: Makefile
===================================================================
--- Makefile	(revision 6554)
+++ Makefile	(working copy)
@@ -12,7 +12,7 @@
 TOPLEVEL_INCLUDED=YES
 
 ifndef KERNEL_DIR
-KERNEL_DIR=/usr/src/linux
+KERNEL_DIR=/usr/src/linux-2.6.15.2
 endif
 IPTABLES_VERSION:=1.3.5
 OLD_IPTABLES_VERSION:=1.3.4



More information about the netfilter-devel mailing list