[PATCH 6/6] IPv4/IPv6 specific extensions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The IPv4/IPv6 extensions with the new error reporting methods.

Signed-off-by: Jozsef Kadlecsik <kadlec@xxxxxxxxxxxxxxxxx>
---

 include/linux/netfilter/xt_CLASSIFY.h    |    7 ++++
 include/linux/netfilter/xt_CONNMARK.h    |    8 ++++
 include/linux/netfilter/xt_CONNSECMARK.h |    8 ++++
 include/linux/netfilter/xt_LED.h         |    8 ++++
 include/linux/netfilter/xt_MARK.h        |    8 ++++
 include/linux/netfilter/xt_NFLOG.h       |    7 ++++
 include/linux/netfilter/xt_NFQUEUE.h     |    7 ++++
 include/linux/netfilter/xt_NOTRACK.h     |   10 +++++
 include/linux/netfilter/xt_RATEEST.h     |    8 ++++
 include/linux/netfilter/xt_SECMARK.h     |   11 ++++++
 include/linux/netfilter/xt_TCPMSS.h      |    8 ++++
 include/linux/netfilter/xt_TCPOPTSTRIP.h |    7 ++++
 include/linux/netfilter/xt_TPROXY.h      |    8 ++++
 include/linux/netfilter/xt_TRACE.h       |   10 +++++
 include/linux/netfilter/xt_cluster.h     |    7 ++++
 include/linux/netfilter/xt_connbytes.h   |    8 ++++
 include/linux/netfilter/xt_connlimit.h   |    7 ++++
 include/linux/netfilter/xt_connmark.h    |    7 ++++
 include/linux/netfilter/xt_conntrack.h   |    6 +++
 include/linux/netfilter/xt_dccp.h        |    8 ++++
 include/linux/netfilter/xt_dscp.h        |    8 ++++
 include/linux/netfilter/xt_esp.h         |    7 ++++
 include/linux/netfilter/xt_hashlimit.h   |   12 ++++++
 include/linux/netfilter/xt_helper.h      |    6 +++
 include/linux/netfilter/xt_limit.h       |    7 ++++
 include/linux/netfilter/xt_mac.h         |    6 +++
 include/linux/netfilter/xt_mark.h        |    6 +++
 include/linux/netfilter/xt_multiport.h   |    9 +++++
 include/linux/netfilter/xt_osf.h         |    7 ++++
 include/linux/netfilter/xt_owner.h       |    7 ++++
 include/linux/netfilter/xt_physdev.h     |    8 ++++
 include/linux/netfilter/xt_policy.h      |    9 +++++
 include/linux/netfilter/xt_quota.h       |    7 ++++
 include/linux/netfilter/xt_rateest.h     |   10 +++++
 include/linux/netfilter/xt_realm.h       |    6 +++
 include/linux/netfilter/xt_recent.h      |   12 ++++++
 include/linux/netfilter/xt_sctp.h        |    9 +++++
 include/linux/netfilter/xt_socket.h      |    6 +++
 include/linux/netfilter/xt_state.h       |    6 +++
 include/linux/netfilter/xt_statistic.h   |    8 ++++
 include/linux/netfilter/xt_string.h      |   10 +++++
 include/linux/netfilter/xt_tcpmss.h      |    6 +++
 include/linux/netfilter/xt_tcpudp.h      |    7 ++++
 include/linux/netfilter/xt_time.h        |    6 +++
 net/netfilter/xt_CLASSIFY.c              |   25 +++++++++++--
 net/netfilter/xt_CONNMARK.c              |   32 ++++++++--------
 net/netfilter/xt_CONNSECMARK.c           |   20 +++++-----
 net/netfilter/xt_DSCP.c                  |   44 ++++++++++++++++------
 net/netfilter/xt_HL.c                    |   36 +++++++++++-------
 net/netfilter/xt_LED.c                   |   22 ++++++-----
 net/netfilter/xt_MARK.c                  |   45 ++++++++++++++---------
 net/netfilter/xt_NFLOG.c                 |   14 ++++---
 net/netfilter/xt_NFQUEUE.c               |    8 ++--
 net/netfilter/xt_NOTRACK.c               |   14 +++++++
 net/netfilter/xt_RATEEST.c               |   19 ++++++----
 net/netfilter/xt_SECMARK.c               |   49 +++++++++++++------------
 net/netfilter/xt_TCPMSS.c                |   38 +++++++++++--------
 net/netfilter/xt_TCPOPTSTRIP.c           |   21 +++++++++--
 net/netfilter/xt_TPROXY.c                |   29 +++++++++------
 net/netfilter/xt_TRACE.c                 |   14 +++++++
 net/netfilter/xt_cluster.c               |   19 +++++-----
 net/netfilter/xt_connbytes.c             |   14 ++++---
 net/netfilter/xt_connlimit.c             |   12 +++---
 net/netfilter/xt_connmark.c              |   24 ++++++------
 net/netfilter/xt_conntrack.c             |   10 +++--
 net/netfilter/xt_dccp.c                  |   21 +++++++----
 net/netfilter/xt_dscp.c                  |    8 ++--
 net/netfilter/xt_esp.c                   |   17 +++++----
 net/netfilter/xt_hashlimit.c             |   40 +++++++++++---------
 net/netfilter/xt_helper.c                |   10 +++--
 net/netfilter/xt_limit.c                 |   10 +++--
 net/netfilter/xt_mac.c                   |   19 +++++++++-
 net/netfilter/xt_mark.c                  |    8 ++--
 net/netfilter/xt_multiport.c             |   59 ++++++++++++------------------
 net/netfilter/xt_osf.c                   |   23 ++++++++++--
 net/netfilter/xt_owner.c                 |   42 +++++++++++++--------
 net/netfilter/xt_physdev.c               |   19 ++++++----
 net/netfilter/xt_policy.c                |   26 +++++++------
 net/netfilter/xt_quota.c                 |   12 ++++--
 net/netfilter/xt_rateest.c               |   24 +++++++++---
 net/netfilter/xt_realm.c                 |   18 ++++++++-
 net/netfilter/xt_recent.c                |   28 +++++++++-----
 net/netfilter/xt_sctp.c                  |   32 ++++++++++------
 net/netfilter/xt_socket.c                |   16 +++++++-
 net/netfilter/xt_state.c                 |   10 +++--
 net/netfilter/xt_statistic.c             |   17 +++++----
 net/netfilter/xt_string.c                |   22 +++++++----
 net/netfilter/xt_tcpmss.c                |   13 ++++++-
 net/netfilter/xt_tcpudp.c                |   54 ++++++++++++++++++++-------
 net/netfilter/xt_time.c                  |   10 +++--
 90 files changed, 1002 insertions(+), 408 deletions(-)

diff --git a/include/linux/netfilter/xt_CLASSIFY.h b/include/linux/netfilter/xt_CLASSIFY.h
index a813bf1..350e5d8 100644
--- a/include/linux/netfilter/xt_CLASSIFY.h
+++ b/include/linux/netfilter/xt_CLASSIFY.h
@@ -3,6 +3,13 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_CLASSIFY_ERR_NONE,
+	XT_CLASSIFY_ERR_MANGLE_TABLE,
+	XT_CLASSIFY_ERR_HOOKS_234,
+	XT_CLASSIFY_ERR_MAX,
+};
+
 struct xt_classify_target_info {
 	__u32 priority;
 };
diff --git a/include/linux/netfilter/xt_CONNMARK.h b/include/linux/netfilter/xt_CONNMARK.h
index 7635c8f..9410032 100644
--- a/include/linux/netfilter/xt_CONNMARK.h
+++ b/include/linux/netfilter/xt_CONNMARK.h
@@ -13,6 +13,14 @@
  */
 
 enum {
+	XT_CONNMARK_ERR_NONE,
+	XT_CONNMARK_ERR_MANGLE_TABLE,
+	XT_CONNMARK_ERR_32BIT_MARK,
+	XT_CONNMARK_ERR_CONNTRACK,
+	XT_CONNMARK_ERR_MAX,
+};	
+
+enum {
 	XT_CONNMARK_SET = 0,
 	XT_CONNMARK_SAVE,
 	XT_CONNMARK_RESTORE
diff --git a/include/linux/netfilter/xt_CONNSECMARK.h b/include/linux/netfilter/xt_CONNSECMARK.h
index b973ff8..756cc91 100644
--- a/include/linux/netfilter/xt_CONNSECMARK.h
+++ b/include/linux/netfilter/xt_CONNSECMARK.h
@@ -4,6 +4,14 @@
 #include <linux/types.h>
 
 enum {
+	XT_CONNSECMARK_ERR_NONE,
+	XT_CONNSECMARK_ERR_MANGLE_SECURITY_TABLES,
+	XT_CONNSECMARK_ERR_MODE,
+	XT_CONNSECMARK_ERR_CONNTRACK,
+	XT_CONNSECMARK_ERR_MAX,
+};
+
+enum {
 	CONNSECMARK_SAVE = 1,
 	CONNSECMARK_RESTORE,
 };
diff --git a/include/linux/netfilter/xt_LED.h b/include/linux/netfilter/xt_LED.h
index f5509e7..1a8ed12 100644
--- a/include/linux/netfilter/xt_LED.h
+++ b/include/linux/netfilter/xt_LED.h
@@ -3,6 +3,14 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_LED_ERR_NONE,
+	XT_LED_ERR_ID,
+	XT_LED_ERR_ALLOC,
+	XT_LED_ERR_REGISTER,
+	XT_LED_ERR_MAX,
+};
+
 struct xt_led_info {
 	char id[27];        /* Unique ID for this trigger in the LED class */
 	__u8 always_blink;  /* Blink even if the LED is already on */
diff --git a/include/linux/netfilter/xt_MARK.h b/include/linux/netfilter/xt_MARK.h
index 028304b..59f404d 100644
--- a/include/linux/netfilter/xt_MARK.h
+++ b/include/linux/netfilter/xt_MARK.h
@@ -3,6 +3,14 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_MARK_ERR_NONE,
+	XT_MARK_ERR_MANGLE_TABLE,
+	XT_MARK_ERR_32BIT_MARK,
+	XT_MARK_ERR_MODE,
+	XT_MARK_ERR_MAX,
+};
+
 /* Version 0 */
 struct xt_mark_target_info {
 	unsigned long mark;
diff --git a/include/linux/netfilter/xt_NFLOG.h b/include/linux/netfilter/xt_NFLOG.h
index 87b5831..5ba31a5 100644
--- a/include/linux/netfilter/xt_NFLOG.h
+++ b/include/linux/netfilter/xt_NFLOG.h
@@ -8,6 +8,13 @@
 
 #define XT_NFLOG_MASK			0x0
 
+enum {
+	XT_NFLOG_ERR_NONE,
+	XT_NFLOG_ERR_FLAGS,
+	XT_NFLOG_ERR_PREFIXLEN,
+	XT_NFLOG_ERR_MAX,
+};
+
 struct xt_nflog_info {
 	__u32	len;
 	__u16	group;
diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h
index 2584f4a..f74d5a7 100644
--- a/include/linux/netfilter/xt_NFQUEUE.h
+++ b/include/linux/netfilter/xt_NFQUEUE.h
@@ -10,6 +10,13 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_NFQUEUE_ERR_NONE,
+	XT_NFQUEUE_ERR_TOTAL_QUEUES,
+	XT_NFQUEUE_ERR_RANGE,
+	XT_NFQUEUE_ERR_MAX,
+};
+
 /* target info */
 struct xt_NFQ_info {
 	__u16 queuenum;
diff --git a/include/linux/netfilter/xt_NOTRACK.h b/include/linux/netfilter/xt_NOTRACK.h
new file mode 100644
index 0000000..a095f97
--- /dev/null
+++ b/include/linux/netfilter/xt_NOTRACK.h
@@ -0,0 +1,10 @@
+#ifndef _X_NOTRACK_H
+#define _X_NOTRACK_H
+
+enum {
+	XT_NOTRACK_ERR_NONE,
+	XT_NOTRACK_ERR_RAW_TABLE,
+	XT_NOTRACK_ERR_MAX,
+};
+
+#endif /*_X_NOTRACK_H */
diff --git a/include/linux/netfilter/xt_RATEEST.h b/include/linux/netfilter/xt_RATEEST.h
index 6605e20..7dcd191 100644
--- a/include/linux/netfilter/xt_RATEEST.h
+++ b/include/linux/netfilter/xt_RATEEST.h
@@ -3,6 +3,14 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_RATEEST_ERR_NONE,
+	XT_RATEEST_ERR_NAME,
+	XT_RATEEST_ERR_ALLOC,
+	XT_RATEEST_ERR_GEN_NEW,
+	XT_RATEEST_ERR_MAX,
+};
+
 struct xt_rateest_target_info {
 	char			name[IFNAMSIZ];
 	__s8			interval;
diff --git a/include/linux/netfilter/xt_SECMARK.h b/include/linux/netfilter/xt_SECMARK.h
index 6fcd344..44ed105 100644
--- a/include/linux/netfilter/xt_SECMARK.h
+++ b/include/linux/netfilter/xt_SECMARK.h
@@ -13,6 +13,17 @@
 #define SECMARK_MODE_SEL	0x01		/* SELinux */
 #define SECMARK_SELCTX_MAX	256
 
+enum {
+	XT_SECMARK_ERR_NONE,
+	XT_SECMARK_ERR_MANGLE_SECURITY_TABLE,
+	XT_SECMARK_ERR_MIXED_MODE,
+	XT_SECMARK_ERR_INVALID_MODE,
+	XT_SECMARK_ERR_CONTEXT,
+	XT_SECMARK_ERR_MAP_CONTEXT,
+	XT_SECMARK_ERR_PERM,
+	XT_SECMARK_ERR_MAX,
+};
+
 struct xt_secmark_target_selinux_info {
 	__u32 selsid;
 	char selctx[SECMARK_SELCTX_MAX];
diff --git a/include/linux/netfilter/xt_TCPMSS.h b/include/linux/netfilter/xt_TCPMSS.h
index 9a6960a..a623da6 100644
--- a/include/linux/netfilter/xt_TCPMSS.h
+++ b/include/linux/netfilter/xt_TCPMSS.h
@@ -3,6 +3,14 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_TCPMSS_ERR_NONE,
+	XT_TCPMSS_ERR_PROTO,
+	XT_TCPMSS_ERR_HOOKS_234,
+	XT_TCPMSS_ERR_SYN,
+	XT_TCPMSS_ERR_MAX,
+};
+
 struct xt_tcpmss_info {
 	__u16 mss;
 };
diff --git a/include/linux/netfilter/xt_TCPOPTSTRIP.h b/include/linux/netfilter/xt_TCPOPTSTRIP.h
index 2db5432..0cec1e1 100644
--- a/include/linux/netfilter/xt_TCPOPTSTRIP.h
+++ b/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -6,6 +6,13 @@
 #define tcpoptstrip_test_bit(bmap, idx) \
 	(((1U << (idx & 31)) & bmap[(idx) >> 5]) != 0)
 
+enum {
+	XT_TCPOPTSTRIP_ERR_NONE,
+	XT_TCPOPTSTRIP_ERR_MANGLE_TABLE,
+	XT_TCPOPTSTRIP_ERR_PROTO,
+	XT_TCPOPTSTRIP_ERR_MAX,
+};
+
 struct xt_tcpoptstrip_target_info {
 	u_int32_t strip_bmap[8];
 };
diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h
index 152e8f9..068a385 100644
--- a/include/linux/netfilter/xt_TPROXY.h
+++ b/include/linux/netfilter/xt_TPROXY.h
@@ -1,6 +1,14 @@
 #ifndef _XT_TPROXY_H_target
 #define _XT_TPROXY_H_target
 
+enum {
+	XT_TPROXY_ERR_NONE,
+	XT_TPROXY_ERR_MANGLE_TABLE,
+	XT_TPROXY_ERR_HOOKS_0,
+	XT_TPROXY_ERR_PROTO,
+	XT_TPROXY_ERR_MAX,
+};
+
 /* TPROXY target is capable of marking the packet to perform
  * redirection. We can get rid of that whenever we get support for
  * mutliple targets in the same rule. */
diff --git a/include/linux/netfilter/xt_TRACE.h b/include/linux/netfilter/xt_TRACE.h
new file mode 100644
index 0000000..1440c1a
--- /dev/null
+++ b/include/linux/netfilter/xt_TRACE.h
@@ -0,0 +1,10 @@
+#ifndef _X_TRACE_H
+#define _X_TRACE_H
+
+enum {
+	XT_TRACE_ERR_NONE,
+	XT_TRACE_ERR_RAW_TABLE,
+	XT_TRACE_ERR_MAX,
+};
+
+#endif /*_X_TRACE_H */
diff --git a/include/linux/netfilter/xt_cluster.h b/include/linux/netfilter/xt_cluster.h
index 8866826..978b688 100644
--- a/include/linux/netfilter/xt_cluster.h
+++ b/include/linux/netfilter/xt_cluster.h
@@ -1,6 +1,13 @@
 #ifndef _XT_CLUSTER_MATCH_H
 #define _XT_CLUSTER_MATCH_H
 
+enum {
+	XT_CLUSTER_ERR_NONE,
+	XT_CLUSTER_ERR_TOTAL_NODES,
+	XT_CLUSTER_ERR_NODE_MASK,
+	XT_CLUSTER_ERR_MAX,
+};
+
 enum xt_cluster_flags {
 	XT_CLUSTER_F_INV	= (1 << 0)
 };
diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h
index 52bd615..9799627 100644
--- a/include/linux/netfilter/xt_connbytes.h
+++ b/include/linux/netfilter/xt_connbytes.h
@@ -3,6 +3,14 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_CONNBYTES_ERR_NONE,
+	XT_CONNBYTES_ERR_WHAT,
+	XT_CONNBYTES_ERR_DIR,
+	XT_CONNBYTES_ERR_CONNTRACK,
+	XT_CONNBYTES_ERR_MAX,
+};
+
 enum xt_connbytes_what {
 	XT_CONNBYTES_PKTS,
 	XT_CONNBYTES_BYTES,
diff --git a/include/linux/netfilter/xt_connlimit.h b/include/linux/netfilter/xt_connlimit.h
index 7e3284b..fe04450 100644
--- a/include/linux/netfilter/xt_connlimit.h
+++ b/include/linux/netfilter/xt_connlimit.h
@@ -1,6 +1,13 @@
 #ifndef _XT_CONNLIMIT_H
 #define _XT_CONNLIMIT_H
 
+enum {
+	XT_CONNLIMIT_ERR_NONE,
+	XT_CONNLIMIT_ERR_CONNTRACK,
+	XT_CONNLIMIT_ERR_INIT,
+	XT_CONNLIMIT_ERR_MAX,
+};
+
 struct xt_connlimit_data;
 
 struct xt_connlimit_info {
diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h
index 571e266..8efc278 100644
--- a/include/linux/netfilter/xt_connmark.h
+++ b/include/linux/netfilter/xt_connmark.h
@@ -12,6 +12,13 @@
  * (at your option) any later version.
  */
 
+enum {
+	XT_CONNMARK_ERR_NONE,
+	XT_CONNMARK_ERR_32BIT_MARK,
+	XT_CONNMARK_ERR_CONNTRACK,
+	XT_CONNMARK_ERR_MAX,
+};
+
 struct xt_connmark_info {
 	unsigned long mark, mask;
 	__u8 invert;
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
index 3430c77..aa27123 100644
--- a/include/linux/netfilter/xt_conntrack.h
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -15,6 +15,12 @@
 #define XT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
 #define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
 
+enum {
+	XT_CONNTRACK_ERR_NONE,
+	XT_CONNTRACK_ERR_CONNTRACK,
+	XT_CONNTRACK_ERR_MAX,
+};
+
 /* flags, invflags: */
 enum {
 	XT_CONNTRACK_STATE        = 1 << 0,
diff --git a/include/linux/netfilter/xt_dccp.h b/include/linux/netfilter/xt_dccp.h
index a579e1b..f5f0c81 100644
--- a/include/linux/netfilter/xt_dccp.h
+++ b/include/linux/netfilter/xt_dccp.h
@@ -10,6 +10,14 @@
 
 #define XT_DCCP_VALID_FLAGS		0x0f
 
+enum {
+	XT_DCCP_ERR_NONE,
+	XT_DCCP_ERR_PROTO,
+	XT_DCCP_ERR_INVALID_FLAGS,
+	XT_DCCP_ERR_FLAG_INVFLAG,
+	XT_DCCP_ERR_MAX,
+};
+
 struct xt_dccp_info {
 	__u16 dpts[2];  /* Min, Max */
 	__u16 spts[2];  /* Min, Max */
diff --git a/include/linux/netfilter/xt_dscp.h b/include/linux/netfilter/xt_dscp.h
index 15f8932..876a2a2 100644
--- a/include/linux/netfilter/xt_dscp.h
+++ b/include/linux/netfilter/xt_dscp.h
@@ -16,6 +16,14 @@
 #define XT_DSCP_SHIFT	2
 #define XT_DSCP_MAX	0x3f	/* 00111111 */
 
+enum {
+	XT_DSCP_ERR_NONE,
+	XT_DSCP_ERR_MANGLE_TABLE,
+	XT_DSCP_ERR_RANGE,
+	XT_DSCP_ERR_VALUE,
+	XT_DSCP_ERR_MAX,
+};
+
 /* match info */
 struct xt_dscp_info {
 	__u8 dscp;
diff --git a/include/linux/netfilter/xt_esp.h b/include/linux/netfilter/xt_esp.h
index ef6fa47..7c77f0a 100644
--- a/include/linux/netfilter/xt_esp.h
+++ b/include/linux/netfilter/xt_esp.h
@@ -3,6 +3,13 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_ESP_ERR_NONE,
+	XT_ESP_ERR_PROTO,
+	XT_ESP_ERR_FLAGS,
+	XT_ESP_ERR_MAX,
+};
+
 struct xt_esp
 {
 	__u32 spis[2];	/* Security Parameter Index */
diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h
index b1925b5..3c299b9 100644
--- a/include/linux/netfilter/xt_hashlimit.h
+++ b/include/linux/netfilter/xt_hashlimit.h
@@ -8,6 +8,18 @@
 /* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
    seconds, or one every 59 hours. */
 
+enum {
+	XT_HASHLIMIT_ERR_NONE,
+	XT_HASHLIMIT_ERR_OVERFLOW,
+	XT_HASHLIMIT_ERR_MODE,
+	XT_HASHLIMIT_ERR_INTERVAL,
+	XT_HASHLIMIT_ERR_EXPIRE,
+	XT_HASHLIMIT_ERR_NAMELEN,
+	XT_HASHLIMIT_ERR_INIT,
+	XT_HASHLIMIT_ERR_NETMASK,
+	XT_HASHLIMIT_ERR_MAX,
+};
+
 /* details of this structure hidden by the implementation */
 struct xt_hashlimit_htable;
 
diff --git a/include/linux/netfilter/xt_helper.h b/include/linux/netfilter/xt_helper.h
index 6b42763..1b43471 100644
--- a/include/linux/netfilter/xt_helper.h
+++ b/include/linux/netfilter/xt_helper.h
@@ -1,6 +1,12 @@
 #ifndef _XT_HELPER_H
 #define _XT_HELPER_H
 
+enum {
+	XT_HELPER_ERR_NONE,
+	XT_HELPER_ERR_CONNTRACK,
+	XT_HELPER_ERR_MAX,
+};
+
 struct xt_helper_info {
 	int invert;
 	char name[30];
diff --git a/include/linux/netfilter/xt_limit.h b/include/linux/netfilter/xt_limit.h
index bb47fc4..dfb666a 100644
--- a/include/linux/netfilter/xt_limit.h
+++ b/include/linux/netfilter/xt_limit.h
@@ -6,6 +6,13 @@
 /* timings are in milliseconds. */
 #define XT_LIMIT_SCALE 10000
 
+enum {
+	XT_LIMIT_ERR_NONE,
+	XT_LIMIT_ERR_OVERFLOW,
+	XT_LIMIT_ERR_ALLOC,
+	XT_LIMIT_ERR_MAX,
+};
+
 struct xt_limit_priv;
 
 /* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
diff --git a/include/linux/netfilter/xt_mac.h b/include/linux/netfilter/xt_mac.h
index b892cdc..c91695c 100644
--- a/include/linux/netfilter/xt_mac.h
+++ b/include/linux/netfilter/xt_mac.h
@@ -1,6 +1,12 @@
 #ifndef _XT_MAC_H
 #define _XT_MAC_H
 
+enum {
+	XT_MAC_ERR_NONE,
+	XT_MAC_ERR_HOOKS_012,
+	XT_MAC_ERR_MAX,
+};
+
 struct xt_mac_info {
     unsigned char srcaddr[ETH_ALEN];
     int invert;
diff --git a/include/linux/netfilter/xt_mark.h b/include/linux/netfilter/xt_mark.h
index 6fa460a..93d8ba0 100644
--- a/include/linux/netfilter/xt_mark.h
+++ b/include/linux/netfilter/xt_mark.h
@@ -3,6 +3,12 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_MARK_ERR_NONE,
+	XT_MARK_ERR_32BIT_MARK,
+	XT_MARK_ERR_MAX,
+};
+
 struct xt_mark_info {
     unsigned long mark, mask;
     __u8 invert;
diff --git a/include/linux/netfilter/xt_multiport.h b/include/linux/netfilter/xt_multiport.h
index 185db49..6a75eb0 100644
--- a/include/linux/netfilter/xt_multiport.h
+++ b/include/linux/netfilter/xt_multiport.h
@@ -3,6 +3,15 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_MULTIPORT_ERR_NONE,
+	XT_MULTIPORT_ERR_PROTO,
+	XT_MULTIPORT_ERR_INV_PROTO,
+	XT_MULTIPORT_ERR_FLAGS,
+	XT_MULTIPORT_ERR_COUNT,
+	XT_MULTIPORT_ERR_MAX,
+};
+
 enum xt_multiport_flags
 {
 	XT_MULTIPORT_SOURCE,
diff --git a/include/linux/netfilter/xt_osf.h b/include/linux/netfilter/xt_osf.h
index fd2272e..a9ccb76 100644
--- a/include/linux/netfilter/xt_osf.h
+++ b/include/linux/netfilter/xt_osf.h
@@ -35,6 +35,13 @@
 #define XT_OSF_TTL_LESS		1	/* Check if ip TTL is less than fingerprint one */
 #define XT_OSF_TTL_NOCHECK	2	/* Do not compare ip and fingerprint TTL at all */
 
+enum {
+	XT_OSF_ERR_NONE,
+	XT_OSF_ERR_HOOKS_012,
+	XT_OSF_ERR_NOT_TCP,
+	XT_OSF_ERR_MAX,
+};
+
 struct xt_osf_info {
 	char			genre[MAXGENRELEN];
 	__u32			len;
diff --git a/include/linux/netfilter/xt_owner.h b/include/linux/netfilter/xt_owner.h
index 2081761..5e2eaa5 100644
--- a/include/linux/netfilter/xt_owner.h
+++ b/include/linux/netfilter/xt_owner.h
@@ -4,6 +4,13 @@
 #include <linux/types.h>
 
 enum {
+	XT_OWNER_ERR_NONE,
+	XT_OWNER_ERR_HOOKS_34,
+	XT_OWNER_ERR_UNSUPPORTED,
+	XT_OWNER_ERR_MAX,
+};
+
+enum {
 	XT_OWNER_UID    = 1 << 0,
 	XT_OWNER_GID    = 1 << 1,
 	XT_OWNER_SOCKET = 1 << 2,
diff --git a/include/linux/netfilter/xt_physdev.h b/include/linux/netfilter/xt_physdev.h
index 8555e39..04b0b74 100644
--- a/include/linux/netfilter/xt_physdev.h
+++ b/include/linux/netfilter/xt_physdev.h
@@ -14,6 +14,14 @@
 #define XT_PHYSDEV_OP_ISOUT		0x10
 #define XT_PHYSDEV_OP_MASK		(0x20 - 1)
 
+enum {
+	XT_PHYSDEV_ERR_NONE,
+	XT_PHYSDEV_ERR_MASK,
+	XT_PHYSDEV_ERR_UNKNOWN,
+	XT_PHYSDEV_ERR_UNSUPPORTED_HOOKS_234,
+	XT_PHYSDEV_ERR_MAX,
+};
+
 struct xt_physdev_info {
 	char physindev[IFNAMSIZ];
 	char in_mask[IFNAMSIZ];
diff --git a/include/linux/netfilter/xt_policy.h b/include/linux/netfilter/xt_policy.h
index 7bb64e7..ffc0201 100644
--- a/include/linux/netfilter/xt_policy.h
+++ b/include/linux/netfilter/xt_policy.h
@@ -5,6 +5,15 @@
 
 #define XT_POLICY_MAX_ELEM	4
 
+enum {
+	XT_POLICY_ERR_NONE,
+	XT_POLICY_ERR_FLAGS,
+	XT_POLICY_ERR_INVALID_OUTPUT_HOOKS_01,
+	XT_POLICY_ERR_INVALID_INPUT_HOOKS_34,
+	XT_POLICY_ERR_MAX_ELEM,
+	XT_POLICY_ERR_MAX,
+};
+
 enum xt_policy_flags
 {
 	XT_POLICY_MATCH_IN	= 0x1,
diff --git a/include/linux/netfilter/xt_quota.h b/include/linux/netfilter/xt_quota.h
index 8dc89df..a09db05 100644
--- a/include/linux/netfilter/xt_quota.h
+++ b/include/linux/netfilter/xt_quota.h
@@ -1,6 +1,13 @@
 #ifndef _XT_QUOTA_H
 #define _XT_QUOTA_H
 
+enum {
+	XT_QUOTA_ERR_NONE,
+	XT_QUOTA_ERR_FLAGS,
+	XT_QUOTA_ERR_ALLOC,
+	XT_QUOTA_ERR_MAX,
+};
+
 enum xt_quota_flags {
 	XT_QUOTA_INVERT		= 0x1,
 };
diff --git a/include/linux/netfilter/xt_rateest.h b/include/linux/netfilter/xt_rateest.h
index d40a619..4a10786 100644
--- a/include/linux/netfilter/xt_rateest.h
+++ b/include/linux/netfilter/xt_rateest.h
@@ -3,6 +3,16 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_RATEEST_ERR_NONE,
+	XT_RATEEST_ERR_ABS,
+	XT_RATEEST_ERR_BPS,
+	XT_RATEEST_ERR_MODE,
+	XT_RATEEST_ERR_NAME1,
+	XT_RATEEST_ERR_NAME2,
+	XT_RATEEST_ERR_MAX,
+};
+
 enum xt_rateest_match_flags {
 	XT_RATEEST_MATCH_INVERT	= 1<<0,
 	XT_RATEEST_MATCH_ABS	= 1<<1,
diff --git a/include/linux/netfilter/xt_realm.h b/include/linux/netfilter/xt_realm.h
index d4a82ee..3a93459 100644
--- a/include/linux/netfilter/xt_realm.h
+++ b/include/linux/netfilter/xt_realm.h
@@ -3,6 +3,12 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_REALM_ERR_NONE,
+	XT_REALM_ERR_HOOKS_1234,
+	XT_REALM_ERR_MAX,
+};
+
 struct xt_realm_info {
 	__u32 id;
 	__u32 mask;
diff --git a/include/linux/netfilter/xt_recent.h b/include/linux/netfilter/xt_recent.h
index d2c2766..b516d2f 100644
--- a/include/linux/netfilter/xt_recent.h
+++ b/include/linux/netfilter/xt_recent.h
@@ -4,6 +4,18 @@
 #include <linux/types.h>
 
 enum {
+	XT_RECENT_ERR_NONE,
+	XT_RECENT_ERR_CHECK_SET,
+	XT_RECENT_ERR_SET,
+	XT_RECENT_ERR_HIT_COUNT,
+	XT_RECENT_ERR_NAME,
+	XT_RECENT_ERR_ALLOC,
+	XT_RECENT_ERR_PROC,
+	XT_RECENT_ERR_PROC_ENTRY,
+	XT_RECENT_ERR_MAX,
+};
+
+enum {
 	XT_RECENT_CHECK    = 1 << 0,
 	XT_RECENT_SET      = 1 << 1,
 	XT_RECENT_UPDATE   = 1 << 2,
diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h
index 29287be..c3f18b0 100644
--- a/include/linux/netfilter/xt_sctp.h
+++ b/include/linux/netfilter/xt_sctp.h
@@ -9,6 +9,15 @@
 
 #define XT_SCTP_VALID_FLAGS		0x07
 
+enum {
+	XT_SCTP_ERR_NONE,
+	XT_SCTP_ERR_PROTO,
+	XT_SCTP_ERR_INVALID_FLAGS,
+	XT_SCTP_ERR_FLAG_INVFLAG,
+	XT_SCTP_ERR_CHUNK,
+	XT_SCTP_ERR_MAX,
+};
+
 struct xt_sctp_flag_info {
 	__u8 chunktype;
 	__u8 flag;
diff --git a/include/linux/netfilter/xt_socket.h b/include/linux/netfilter/xt_socket.h
index 6f475b8..3b80991 100644
--- a/include/linux/netfilter/xt_socket.h
+++ b/include/linux/netfilter/xt_socket.h
@@ -2,6 +2,12 @@
 #define _XT_SOCKET_H
 
 enum {
+	XT_SOCKET_ERR_NONE,
+	XT_SOCKET_ERR_HOOKS_0,
+	XT_SOCKET_ERR_MAX,
+};
+
+enum {
 	XT_SOCKET_TRANSPARENT = 1 << 0,
 };
 
diff --git a/include/linux/netfilter/xt_state.h b/include/linux/netfilter/xt_state.h
index c06f32e..14c9ea1 100644
--- a/include/linux/netfilter/xt_state.h
+++ b/include/linux/netfilter/xt_state.h
@@ -6,6 +6,12 @@
 
 #define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
 
+enum {
+	XT_STATE_ERR_NONE,
+	XT_STATE_ERR_CONNTRACK,
+	XT_STATE_ERR_MAX,
+};
+
 struct xt_state_info
 {
 	unsigned int statemask;
diff --git a/include/linux/netfilter/xt_statistic.h b/include/linux/netfilter/xt_statistic.h
index 4e983ef..6974972 100644
--- a/include/linux/netfilter/xt_statistic.h
+++ b/include/linux/netfilter/xt_statistic.h
@@ -3,6 +3,14 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_STATISTIC_ERR_NONE,
+	XT_STATISTIC_ERR_MODE,
+	XT_STATISTIC_ERR_FLAGS,
+	XT_STATISTIC_ERR_ALLOC,
+	XT_STATISTIC_ERR_MAX,
+};
+
 enum xt_statistic_mode {
 	XT_STATISTIC_MODE_RANDOM,
 	XT_STATISTIC_MODE_NTH,
diff --git a/include/linux/netfilter/xt_string.h b/include/linux/netfilter/xt_string.h
index ecbb95f..7a98cb9 100644
--- a/include/linux/netfilter/xt_string.h
+++ b/include/linux/netfilter/xt_string.h
@@ -7,6 +7,16 @@
 #define XT_STRING_MAX_ALGO_NAME_SIZE 16
 
 enum {
+	XT_STRING_ERR_NONE,
+	XT_STRING_ERR_OFFSET,
+	XT_STRING_ERR_ALGO_NAME,
+	XT_STRING_ERR_PATLEN,
+	XT_STRING_ERR_IGNORECASE,
+	XT_STRING_ERR_PREPARE,
+	XT_STRING_ERR_MAX,
+};
+
+enum {
 	XT_STRING_FLAG_INVERT		= 0x01,
 	XT_STRING_FLAG_IGNORECASE	= 0x02
 };
diff --git a/include/linux/netfilter/xt_tcpmss.h b/include/linux/netfilter/xt_tcpmss.h
index fbac56b..9d5ba56 100644
--- a/include/linux/netfilter/xt_tcpmss.h
+++ b/include/linux/netfilter/xt_tcpmss.h
@@ -3,6 +3,12 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_TCPMSS_ERR_NONE,
+	XT_TCPMSS_ERR_PROTO,
+	XT_TCPMSS_ERR_MAX,
+};
+
 struct xt_tcpmss_match_info {
     __u16 mss_min, mss_max;
     __u8 invert;
diff --git a/include/linux/netfilter/xt_tcpudp.h b/include/linux/netfilter/xt_tcpudp.h
index a490a0b..bbf4d65 100644
--- a/include/linux/netfilter/xt_tcpudp.h
+++ b/include/linux/netfilter/xt_tcpudp.h
@@ -3,6 +3,13 @@
 
 #include <linux/types.h>
 
+enum {
+	XT_TCPUDP_ERR_NONE,
+	XT_TCPUDP_ERR_PROTO,
+	XT_TCPUDP_ERR_FLAGS,
+	XT_TCPUDP_ERR_MAX,
+};
+
 /* TCP matching stuff */
 struct xt_tcp
 {
diff --git a/include/linux/netfilter/xt_time.h b/include/linux/netfilter/xt_time.h
index 14b6df4..dae46c2 100644
--- a/include/linux/netfilter/xt_time.h
+++ b/include/linux/netfilter/xt_time.h
@@ -1,6 +1,12 @@
 #ifndef _XT_TIME_H
 #define _XT_TIME_H 1
 
+enum {
+	XT_TIME_ERR_NONE,
+	XT_TIME_ERR_INVALID,
+	XT_TIME_ERR_MAX,
+};
+
 struct xt_time_info {
 	u_int32_t date_start;
 	u_int32_t date_stop;
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 011bc80..ad183ef 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -35,13 +35,32 @@ classify_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
+static unsigned int
+classify_tg_check(const struct xt_tgchk_param *par)
+{
+	unsigned int valid_hooks =
+		(1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
+		(1 << NF_INET_POST_ROUTING);
+
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "CLASSIFY target can only be used in the "
+			      "\"mangle\" table.");
+	    	return XT_CLASSIFY_ERR_MANGLE_TABLE;
+	}
+	if ((par->hook_mask & ~valid_hooks) != 0) {
+		xt_compat_log(par, "CLASSIFY target can only be used in the "
+			      "FORWARD, OUTPUT and POSTROUTING chains.");
+		return XT_CLASSIFY_ERR_HOOKS_234;
+	}
+
+	return XT_CLASSIFY_ERR_NONE;
+}
+
 static struct xt_target classify_tg_reg __read_mostly = {
 	.name       = "CLASSIFY",
 	.revision   = 0,
 	.family     = NFPROTO_UNSPEC,
-	.table      = "mangle",
-	.hooks      = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
-		      (1 << NF_INET_POST_ROUTING),
+	.checkentry = classify_tg_check,
 	.target     = classify_tg,
 	.targetsize = sizeof(struct xt_classify_target_info),
 	.me         = THIS_MODULE,
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index d6e5ab4..1285cb6 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -112,38 +112,38 @@ connmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
-static bool connmark_tg_check_v0(const struct xt_tgchk_param *par)
+static unsigned int connmark_tg_check_v0(const struct xt_tgchk_param *par)
 {
 	const struct xt_connmark_target_info *matchinfo = par->targinfo;
 
 	if (matchinfo->mode == XT_CONNMARK_RESTORE) {
 		if (strcmp(par->table, "mangle") != 0) {
-			printk(KERN_WARNING "CONNMARK: restore can only be "
-			       "called from \"mangle\" table, not \"%s\"\n",
-			       par->table);
-			return false;
+			xt_compat_log(par, "CONNMARK: restore can only be "
+				"called from \"mangle\" table, not \"%s\"",
+				par->table);
+			return XT_CONNMARK_ERR_MANGLE_TABLE;
 		}
 	}
 	if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
-		printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
-		return false;
+		xt_compat_log(par, "CONNMARK: Only supports 32bit mark");
+		return XT_CONNMARK_ERR_32BIT_MARK;
 	}
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
-				    "proto=%u\n", par->family);
-		return false;
+		xt_compat_log(par, "can't load conntrack support for "
+			      "proto=%u", par->family);
+		return XT_CONNMARK_ERR_CONNTRACK;
 	}
-	return true;
+	return XT_CONNMARK_ERR_NONE;
 }
 
-static bool connmark_tg_check(const struct xt_tgchk_param *par)
+static unsigned int connmark_tg_check(const struct xt_tgchk_param *par)
 {
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "cannot load conntrack support for "
-		       "proto=%u\n", par->family);
-		return false;
+		xt_compat_log(par, "cannot load conntrack support for "
+			      "proto=%u", par->family);
+		return XT_CONNMARK_ERR_CONNTRACK;
 	}
-	return true;
+	return XT_CONNMARK_ERR_NONE;
 }
 
 static void connmark_tg_destroy(const struct xt_tgdtor_param *par)
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index b54c375..1ad4f16 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -85,15 +85,15 @@ connsecmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
-static bool connsecmark_tg_check(const struct xt_tgchk_param *par)
+static unsigned int connsecmark_tg_check(const struct xt_tgchk_param *par)
 {
 	const struct xt_connsecmark_target_info *info = par->targinfo;
 
 	if (strcmp(par->table, "mangle") != 0 &&
 	    strcmp(par->table, "security") != 0) {
-		printk(KERN_INFO PFX "target only valid in the \'mangle\' "
-		       "or \'security\' tables, not \'%s\'.\n", par->table);
-		return false;
+		xt_compat_log(par, PFX "target only valid in the \'mangle\' "
+			"or \'security\' tables, not \'%s\'.", par->table);
+		return XT_CONNSECMARK_ERR_MANGLE_SECURITY_TABLES;
 	}
 
 	switch (info->mode) {
@@ -102,16 +102,16 @@ static bool connsecmark_tg_check(const struct xt_tgchk_param *par)
 		break;
 
 	default:
-		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
-		return false;
+		xt_compat_log(par, PFX "invalid mode: %hu", info->mode);
+		return XT_CONNSECMARK_ERR_MODE;
 	}
 
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
-				    "proto=%u\n", par->family);
-		return false;
+		xt_compat_log(par, "can't load conntrack support for "
+			      "proto=%u", par->family);
+		return XT_CONNSECMARK_ERR_CONNTRACK;
 	}
-	return true;
+	return XT_CONNSECMARK_ERR_NONE;
 }
 
 static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index 6a347e7..e4ebc71 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -61,15 +61,20 @@ dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
-static bool dscp_tg_check(const struct xt_tgchk_param *par)
+static unsigned int dscp_tg_check(const struct xt_tgchk_param *par)
 {
 	const struct xt_DSCP_info *info = par->targinfo;
 
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "DSCP target can only be used in the "
+			      "\"mangle\" table.");
+	    	return XT_DSCP_ERR_MANGLE_TABLE;
+	}
 	if (info->dscp > XT_DSCP_MAX) {
-		printk(KERN_WARNING "DSCP: dscp %x out of range\n", info->dscp);
-		return false;
+		xt_compat_log(par, "DSCP: dscp %x out of range", info->dscp);
+		return XT_DSCP_ERR_RANGE;
 	}
-	return true;
+	return XT_DSCP_ERR_NONE;
 }
 
 static unsigned int
@@ -92,19 +97,24 @@ tos_tg_v0(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
-static bool tos_tg_check_v0(const struct xt_tgchk_param *par)
+static unsigned int tos_tg_check_v0(const struct xt_tgchk_param *par)
 {
 	const struct ipt_tos_target_info *info = par->targinfo;
 	const uint8_t tos = info->tos;
 
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "TOS target can only be used in the "
+			      "\"mangle\" table.");
+	    	return XT_DSCP_ERR_MANGLE_TABLE;
+	}
 	if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT &&
 	    tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST &&
 	    tos != IPTOS_NORMALSVC) {
-		printk(KERN_WARNING "TOS: bad tos value %#x\n", tos);
-		return false;
+		xt_compat_log(par, "TOS: bad tos value %#x\n", tos);
+		return XT_DSCP_ERR_VALUE;
 	}
 
-	return true;
+	return XT_DSCP_ERR_NONE;
 }
 
 static unsigned int
@@ -147,6 +157,17 @@ tos_tg6(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
+static unsigned int tos_tg_check_v1(const struct xt_tgchk_param *par)
+{
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "TOS target can only be used in the "
+			      "\"mangle\" table.");
+	    	return XT_DSCP_ERR_MANGLE_TABLE;
+	}
+
+	return XT_DSCP_ERR_NONE;
+}
+
 static struct xt_target dscp_tg_reg[] __read_mostly = {
 	{
 		.name		= "DSCP",
@@ -154,7 +175,6 @@ static struct xt_target dscp_tg_reg[] __read_mostly = {
 		.checkentry	= dscp_tg_check,
 		.target		= dscp_tg,
 		.targetsize	= sizeof(struct xt_DSCP_info),
-		.table		= "mangle",
 		.me		= THIS_MODULE,
 	},
 	{
@@ -163,14 +183,12 @@ static struct xt_target dscp_tg_reg[] __read_mostly = {
 		.checkentry	= dscp_tg_check,
 		.target		= dscp_tg6,
 		.targetsize	= sizeof(struct xt_DSCP_info),
-		.table		= "mangle",
 		.me		= THIS_MODULE,
 	},
 	{
 		.name		= "TOS",
 		.revision	= 0,
 		.family		= NFPROTO_IPV4,
-		.table		= "mangle",
 		.target		= tos_tg_v0,
 		.targetsize	= sizeof(struct ipt_tos_target_info),
 		.checkentry	= tos_tg_check_v0,
@@ -180,18 +198,18 @@ static struct xt_target dscp_tg_reg[] __read_mostly = {
 		.name		= "TOS",
 		.revision	= 1,
 		.family		= NFPROTO_IPV4,
-		.table		= "mangle",
 		.target		= tos_tg,
 		.targetsize	= sizeof(struct xt_tos_target_info),
+		.checkentry	= tos_tg_check_v1,
 		.me		= THIS_MODULE,
 	},
 	{
 		.name		= "TOS",
 		.revision	= 1,
 		.family		= NFPROTO_IPV6,
-		.table		= "mangle",
 		.target		= tos_tg6,
 		.targetsize	= sizeof(struct xt_tos_target_info),
+		.checkentry	= tos_tg_check_v1,
 		.me		= THIS_MODULE,
 	},
 };
diff --git a/net/netfilter/xt_HL.c b/net/netfilter/xt_HL.c
index 10e789e..9dfa47e 100644
--- a/net/netfilter/xt_HL.c
+++ b/net/netfilter/xt_HL.c
@@ -101,35 +101,45 @@ hl_tg6(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
-static bool ttl_tg_check(const struct xt_tgchk_param *par)
+static unsigned int ttl_tg_check(const struct xt_tgchk_param *par)
 {
 	const struct ipt_TTL_info *info = par->targinfo;
 
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "TTL target can only be used in the "
+			      "\"mangle\" table.");
+	    	return XT_HL_ERR_MANGLE_TABLE;
+	}
 	if (info->mode > IPT_TTL_MAXMODE) {
-		printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
+		xt_compat_log(par, "ipt_TTL: invalid or unknown Mode %u",
 			info->mode);
-		return false;
+		return XT_HL_ERR_MODE;
 	}
 	if (info->mode != IPT_TTL_SET && info->ttl == 0)
-		return false;
-	return true;
+		return XT_HL_ERR_SET;
+	return XT_HL_ERR_NONE;
 }
 
-static bool hl_tg6_check(const struct xt_tgchk_param *par)
+static unsigned int hl_tg6_check(const struct xt_tgchk_param *par)
 {
 	const struct ip6t_HL_info *info = par->targinfo;
 
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "HL target can only be used in the "
+			      "\"mangle\" table.");
+	    	return XT_HL_ERR_MANGLE_TABLE;
+	}
 	if (info->mode > IP6T_HL_MAXMODE) {
-		printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
+		xt_compat_log(par, "ip6t_HL: invalid or unknown Mode %u",
 			info->mode);
-		return false;
+		return XT_HL_ERR_MODE;
 	}
 	if (info->mode != IP6T_HL_SET && info->hop_limit == 0) {
-		printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
-			"make sense with value 0\n");
-		return false;
+		xt_compat_log(par, "ip6t_HL: increment/decrement doesn't "
+			"make sense with value 0");
+		return XT_HL_ERR_SET;
 	}
-	return true;
+	return XT_HL_ERR_NONE;
 }
 
 static struct xt_target hl_tg_reg[] __read_mostly = {
@@ -139,7 +149,6 @@ static struct xt_target hl_tg_reg[] __read_mostly = {
 		.family     = NFPROTO_IPV4,
 		.target     = ttl_tg,
 		.targetsize = sizeof(struct ipt_TTL_info),
-		.table      = "mangle",
 		.checkentry = ttl_tg_check,
 		.me         = THIS_MODULE,
 	},
@@ -149,7 +158,6 @@ static struct xt_target hl_tg_reg[] __read_mostly = {
 		.family     = NFPROTO_IPV6,
 		.target     = hl_tg6,
 		.targetsize = sizeof(struct ip6t_HL_info),
-		.table      = "mangle",
 		.checkentry = hl_tg6_check,
 		.me         = THIS_MODULE,
 	},
diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c
index 8ff7843..0caad04 100644
--- a/net/netfilter/xt_LED.c
+++ b/net/netfilter/xt_LED.c
@@ -80,32 +80,32 @@ static void led_timeout_callback(unsigned long data)
 	led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF);
 }
 
-static bool led_tg_check(const struct xt_tgchk_param *par)
+static unsigned int led_tg_check(const struct xt_tgchk_param *par)
 {
 	struct xt_led_info *ledinfo = par->targinfo;
 	struct xt_led_info_internal *ledinternal;
 	int err;
 
 	if (ledinfo->id[0] == '\0') {
-		printk(KERN_ERR KBUILD_MODNAME ": No 'id' parameter given.\n");
-		return false;
+		xt_compat_log(par, KBUILD_MODNAME ": No 'id' parameter given.");
+		return XT_LED_ERR_ID;
 	}
 
 	ledinternal = kzalloc(sizeof(struct xt_led_info_internal), GFP_KERNEL);
 	if (!ledinternal) {
-		printk(KERN_CRIT KBUILD_MODNAME ": out of memory\n");
-		return false;
+		xt_compat_log(par, KBUILD_MODNAME ": out of memory");
+		return XT_LED_ERR_ALLOC;
 	}
 
 	ledinternal->netfilter_led_trigger.name = ledinfo->id;
 
 	err = led_trigger_register(&ledinternal->netfilter_led_trigger);
 	if (err) {
-		printk(KERN_CRIT KBUILD_MODNAME
-			": led_trigger_register() failed\n");
+		xt_compat_log(par, KBUILD_MODNAME
+			": led_trigger_register() failed");
 		if (err == -EEXIST)
-			printk(KERN_ERR KBUILD_MODNAME
-				": Trigger name is already in use.\n");
+			xt_compat_log(par, KBUILD_MODNAME
+				": Trigger name is already in use.");
 		goto exit_alloc;
 	}
 
@@ -116,12 +116,12 @@ static bool led_tg_check(const struct xt_tgchk_param *par)
 
 	ledinfo->internal_data = ledinternal;
 
-	return true;
+	return XT_LED_ERR_NONE;
 
 exit_alloc:
 	kfree(ledinternal);
 
-	return false;
+	return XT_LED_ERR_REGISTER;
 }
 
 static void led_tg_destroy(const struct xt_tgdtor_param *par)
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 67574bc..0a5629d 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -66,33 +66,46 @@ mark_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
-static bool mark_tg_check_v0(const struct xt_tgchk_param *par)
+static unsigned int mark_tg_check_v0(const struct xt_tgchk_param *par)
 {
-	const struct xt_mark_target_info *markinfo = par->targinfo;
-
+	const struct xt_mark_target_info *markinfo =
+		(struct xt_mark_target_info *) par->targinfo;
+
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "MARK: can only be "
+			"called from \"mangle\" table, not \"%s\"",
+			par->table);
+		return XT_MARK_ERR_MANGLE_TABLE;
+	}
 	if (markinfo->mark > 0xffffffff) {
-		printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
-		return false;
+		xt_compat_log(par, "MARK: Only supports 32bit wide mark");
+		return XT_MARK_ERR_32BIT_MARK;
 	}
-	return true;
+	return XT_MARK_ERR_NONE;
 }
 
-static bool mark_tg_check_v1(const struct xt_tgchk_param *par)
+static unsigned int mark_tg_check_v1(const struct xt_tgchk_param *par)
 {
-	const struct xt_mark_target_info_v1 *markinfo = par->targinfo;
-
+	const struct xt_mark_target_info_v1 *markinfo = 
+		(struct xt_mark_target_info_v1 *) par->targinfo;
+
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "MARK: can only be "
+			"called from \"mangle\" table, not \"%s\"",
+			par->table);
+		return XT_MARK_ERR_MANGLE_TABLE;
+	}
 	if (markinfo->mode != XT_MARK_SET
 	    && markinfo->mode != XT_MARK_AND
 	    && markinfo->mode != XT_MARK_OR) {
-		printk(KERN_WARNING "MARK: unknown mode %u\n",
-		       markinfo->mode);
-		return false;
+		xt_compat_log(par, "MARK: unknown mode %u", markinfo->mode);
+		return XT_MARK_ERR_MODE;
 	}
 	if (markinfo->mark > 0xffffffff) {
-		printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
-		return false;
+		xt_compat_log(par, "MARK: Only supports 32bit wide mark");
+		return XT_MARK_ERR_32BIT_MARK;
 	}
-	return true;
+	return XT_MARK_ERR_NONE;
 }
 
 #ifdef CONFIG_COMPAT
@@ -159,7 +172,6 @@ static struct xt_target mark_tg_reg[] __read_mostly = {
 		.compat_from_user = mark_tg_compat_from_user_v0,
 		.compat_to_user	= mark_tg_compat_to_user_v0,
 #endif
-		.table		= "mangle",
 		.me		= THIS_MODULE,
 	},
 	{
@@ -174,7 +186,6 @@ static struct xt_target mark_tg_reg[] __read_mostly = {
 		.compat_from_user = mark_tg_compat_from_user_v1,
 		.compat_to_user	= mark_tg_compat_to_user_v1,
 #endif
-		.table		= "mangle",
 		.me		= THIS_MODULE,
 	},
 	{
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index a57c5cf..9e5b08e 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -37,15 +37,17 @@ nflog_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
-static bool nflog_tg_check(const struct xt_tgchk_param *par)
+static unsigned int nflog_tg_check(const struct xt_tgchk_param *par)
 {
-	const struct xt_nflog_info *info = par->targinfo;
+	struct xt_nflog_info *info = par->targinfo;
 
 	if (info->flags & ~XT_NFLOG_MASK)
-		return false;
-	if (info->prefix[sizeof(info->prefix) - 1] != '\0')
-		return false;
-	return true;
+		return XT_NFLOG_ERR_FLAGS;
+	if (info->prefix[sizeof(info->prefix) - 1] != '\0') {
+		info->prefix[sizeof(info->prefix) - 1] = '\0';
+		return XT_NFLOG_ERR_PREFIXLEN;
+	}
+	return XT_NFLOG_ERR_NONE;
 }
 
 static struct xt_target nflog_tg_reg __read_mostly = {
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 498b451..52a6187 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -85,22 +85,22 @@ nfqueue_tg6_v1(struct sk_buff *skb, const struct xt_target_param *par)
 }
 #endif
 
-static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
+static unsigned int nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
 {
 	const struct xt_NFQ_info_v1 *info = par->targinfo;
 	u32 maxid;
 
 	if (info->queues_total == 0) {
 		pr_err("NFQUEUE: number of total queues is 0\n");
-		return false;
+		return XT_NFQUEUE_ERR_TOTAL_QUEUES;
 	}
 	maxid = info->queues_total - 1 + info->queuenum;
 	if (maxid > 0xffff) {
 		pr_err("NFQUEUE: number of queues (%u) out of range (got %u)\n",
 		       info->queues_total, maxid);
-		return false;
+		return XT_NFQUEUE_ERR_RANGE;
 	}
-	return true;
+	return XT_NFQUEUE_ERR_NONE;
 }
 
 static struct xt_target nfqueue_tg_reg[] __read_mostly = {
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index e7a0a54..2c8ef92 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -5,6 +5,7 @@
 #include <linux/skbuff.h>
 
 #include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_NOTRACK.h>
 #include <net/netfilter/nf_conntrack.h>
 
 MODULE_DESCRIPTION("Xtables: Disabling connection tracking for packets");
@@ -30,12 +31,23 @@ notrack_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
+static unsigned int notrack_tg_check(const struct xt_tgchk_param *par)
+{
+	if (strcmp(par->table, "raw") != 0) {
+		xt_compat_log(par, "NOTRACK: can only be "
+			"called from \"raw\" table, not \"%s\"",
+			par->table);
+		return XT_NOTRACK_ERR_RAW_TABLE;
+	}
+	return XT_NOTRACK_ERR_NONE;
+}
+
 static struct xt_target notrack_tg_reg __read_mostly = {
 	.name     = "NOTRACK",
 	.revision = 0,
 	.family   = NFPROTO_UNSPEC,
 	.target   = notrack_tg,
-	.table    = "raw",
+	.checkentry = notrack_tg_check,
 	.me       = THIS_MODULE,
 };
 
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
index 43f5676..3696fa9 100644
--- a/net/netfilter/xt_RATEEST.c
+++ b/net/netfilter/xt_RATEEST.c
@@ -84,7 +84,7 @@ xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
-static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
+static unsigned int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
 {
 	struct xt_rateest_target_info *info = par->targinfo;
 	struct xt_rateest *est;
@@ -92,6 +92,7 @@ static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
 		struct nlattr		opt;
 		struct gnet_estimator	est;
 	} cfg;
+	unsigned int ret;
 
 	est = xt_rateest_lookup(info->name);
 	if (est) {
@@ -103,15 +104,17 @@ static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
 		    (info->interval != est->params.interval ||
 		     info->ewma_log != est->params.ewma_log)) {
 			xt_rateest_put(est);
-			return false;
+			return XT_RATEEST_ERR_NAME;
 		}
 		info->est = est;
-		return true;
+		return XT_RATEEST_ERR_NONE;
 	}
 
 	est = kzalloc(sizeof(*est), GFP_KERNEL);
-	if (!est)
+	if (!est) {
+		ret = XT_RATEEST_ERR_ALLOC;
 		goto err1;
+	}
 
 	strlcpy(est->name, info->name, sizeof(est->name));
 	spin_lock_init(&est->lock);
@@ -125,18 +128,20 @@ static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
 	cfg.est.ewma_log	= info->ewma_log;
 
 	if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock,
-			      &cfg.opt) < 0)
+			      &cfg.opt) < 0) {
+		ret = XT_RATEEST_ERR_GEN_NEW;
 		goto err2;
+	}
 
 	info->est = est;
 	xt_rateest_hash_insert(est);
 
-	return true;
+	return XT_RATEEST_ERR_NONE;
 
 err2:
 	kfree(est);
 err1:
-	return false;
+	return ret;
 }
 
 static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par)
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 7a6f9e6..00eb056 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -49,7 +49,7 @@ secmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
-static bool checkentry_selinux(struct xt_secmark_target_info *info)
+static unsigned int checkentry_selinux(struct xt_secmark_target_info *info)
 {
 	int err;
 	struct xt_secmark_target_selinux_info *sel = &info->u.sel;
@@ -59,58 +59,59 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
 	err = selinux_string_to_sid(sel->selctx, &sel->selsid);
 	if (err) {
 		if (err == -EINVAL)
-			printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n",
-			       sel->selctx);
-		return false;
+			xt_compat_log(par, PFX "invalid SELinux context \'%s\'",
+				      sel->selctx);
+		return XT_SECMARK_ERR_CONTEXT;
 	}
 
 	if (!sel->selsid) {
-		printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n",
-		       sel->selctx);
-		return false;
+		xt_compat_log(par, PFX "unable to map SELinux context \'%s\'",
+			      sel->selctx);
+		return XT_SECMARK_ERR_MAP_CONTEXT;
 	}
 
 	err = selinux_secmark_relabel_packet_permission(sel->selsid);
 	if (err) {
-		printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
-		return false;
+		xt_compat_log(par, PFX "unable to obtain relabeling permission");
+		return XT_SECMARK_ERR_PERM;
 	}
 
 	selinux_secmark_refcount_inc();
-	return true;
+	return XT_SECMARK_ERR_NONE;
 }
 
-static bool secmark_tg_check(const struct xt_tgchk_param *par)
+static unsigned int secmark_tg_check(const struct xt_tgchk_param *par)
 {
 	struct xt_secmark_target_info *info = par->targinfo;
 
 	if (strcmp(par->table, "mangle") != 0 &&
 	    strcmp(par->table, "security") != 0) {
-		printk(KERN_INFO PFX "target only valid in the \'mangle\' "
-		       "or \'security\' tables, not \'%s\'.\n", par->table);
-		return false;
+		xt_compat_log(par, PFX "target only valid in the \'mangle\' "
+			"or \'security\' tables, not \'%s\'.", par->table);
+		return XT_SECMARK_ERR_MANGLE_SECURITY_TABLE;
 	}
 
 	if (mode && mode != info->mode) {
-		printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
-		       "rules for mode %hu\n", mode, info->mode);
-		return false;
+		xt_compat_log(par, PFX "mode already set to %hu cannot mix with "
+		       "rules for mode %hu", mode, info->mode);
+		return XT_SECMARK_ERR_MIXED_MODE;
 	}
 
 	switch (info->mode) {
-	case SECMARK_MODE_SEL:
-		if (!checkentry_selinux(info))
-			return false;
+	case SECMARK_MODE_SEL: {
+		unsigned int ret = checkentry_selinux(info);
+		if (ret != 0)
+			return ret;
 		break;
-
+	}
 	default:
-		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
-		return false;
+		xt_compat_log(par, PFX "invalid mode: %hu", info->mode);
+		return XT_SECMARK_ERR_INVALID_MODE;
 	}
 
 	if (!mode)
 		mode = info->mode;
-	return true;
+	return 0;
 }
 
 static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index eda64c1..01523f8 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -237,43 +237,51 @@ static inline bool find_syn_match(const struct xt_entry_match *m)
 	return false;
 }
 
-static bool tcpmss_tg4_check(const struct xt_tgchk_param *par)
+static unsigned int tcpmss_tg4_check(const struct xt_tgchk_param *par)
 {
 	const struct xt_tcpmss_info *info = par->targinfo;
 	const struct ipt_entry *e = par->entryinfo;
 
+	if (par->proto != IPPROTO_TCP || par->inverted) {
+		xt_compat_log(par, "TCPMSS target: only valid for protocol TCP");
+		return XT_TCPMSS_ERR_PROTO;
+	}
 	if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
 	    (par->hook_mask & ~((1 << NF_INET_FORWARD) |
 			   (1 << NF_INET_LOCAL_OUT) |
 			   (1 << NF_INET_POST_ROUTING))) != 0) {
-		printk("xt_TCPMSS: path-MTU clamping only supported in "
-		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
-		return false;
+		xt_compat_log(par, "xt_TCPMSS: path-MTU clamping only supported in "
+		       "FORWARD, OUTPUT and POSTROUTING chains");
+		return XT_TCPMSS_ERR_HOOKS_234;
 	}
 	if (IPT_MATCH_ITERATE(e, find_syn_match))
-		return true;
-	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
-	return false;
+		return XT_TCPMSS_ERR_NONE;
+	xt_compat_log(par, "xt_TCPMSS: Only works on TCP SYN packets");
+	return XT_TCPMSS_ERR_SYN;
 }
 
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
-static bool tcpmss_tg6_check(const struct xt_tgchk_param *par)
+static unsigned int tcpmss_tg6_check(const struct xt_tgchk_param *par)
 {
 	const struct xt_tcpmss_info *info = par->targinfo;
 	const struct ip6t_entry *e = par->entryinfo;
 
+	if (par->proto != IPPROTO_TCP || par->inverted) {
+		xt_compat_log(par, "TCPMSS target: only valid for protocol TCP");
+		return XT_TCPMSS_ERR_PROTO;
+	}
 	if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
 	    (par->hook_mask & ~((1 << NF_INET_FORWARD) |
 			   (1 << NF_INET_LOCAL_OUT) |
 			   (1 << NF_INET_POST_ROUTING))) != 0) {
-		printk("xt_TCPMSS: path-MTU clamping only supported in "
-		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
-		return false;
+		xt_compat_log(par, "xt_TCPMSS: path-MTU clamping only supported in "
+		       "FORWARD, OUTPUT and POSTROUTING chains");
+		return XT_TCPMSS_ERR_HOOKS_234;
 	}
 	if (IP6T_MATCH_ITERATE(e, find_syn_match))
-		return true;
-	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
-	return false;
+		return XT_TCPMSS_ERR_NONE;
+	xt_compat_log(par, "xt_TCPMSS: Only works on TCP SYN packets");
+	return XT_TCPMSS_ERR_SYN;
 }
 #endif
 
@@ -284,7 +292,6 @@ static struct xt_target tcpmss_tg_reg[] __read_mostly = {
 		.checkentry	= tcpmss_tg4_check,
 		.target		= tcpmss_tg4,
 		.targetsize	= sizeof(struct xt_tcpmss_info),
-		.proto		= IPPROTO_TCP,
 		.me		= THIS_MODULE,
 	},
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
@@ -294,7 +301,6 @@ static struct xt_target tcpmss_tg_reg[] __read_mostly = {
 		.checkentry	= tcpmss_tg6_check,
 		.target		= tcpmss_tg6,
 		.targetsize	= sizeof(struct xt_tcpmss_info),
-		.proto		= IPPROTO_TCP,
 		.me		= THIS_MODULE,
 	},
 #endif
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c
index 9dd8c8e..517759b 100644
--- a/net/netfilter/xt_TCPOPTSTRIP.c
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -99,12 +99,26 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_target_param *par)
 }
 #endif
 
+static unsigned int tcpoptstrip_tg_check(const struct xt_tgchk_param *par)
+{
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "TCPOPTSTRIP target: can only be "
+			"called from \"mangle\" table, not \"%s\"",
+			par->table);
+		return XT_TCPOPTSTRIP_ERR_MANGLE_TABLE;
+	}
+	if (par->proto != IPPROTO_TCP || par->inverted) {
+		xt_compat_log(par, "TCPOPTSTRIP target: only valid for protocol TCP");
+		return XT_TCPOPTSTRIP_ERR_PROTO;
+	}
+	return XT_TCPOPTSTRIP_ERR_NONE;
+}
+
 static struct xt_target tcpoptstrip_tg_reg[] __read_mostly = {
 	{
 		.name       = "TCPOPTSTRIP",
 		.family     = NFPROTO_IPV4,
-		.table      = "mangle",
-		.proto      = IPPROTO_TCP,
+		.checkentry = tcpoptstrip_tg_check,
 		.target     = tcpoptstrip_tg4,
 		.targetsize = sizeof(struct xt_tcpoptstrip_target_info),
 		.me         = THIS_MODULE,
@@ -113,8 +127,7 @@ static struct xt_target tcpoptstrip_tg_reg[] __read_mostly = {
 	{
 		.name       = "TCPOPTSTRIP",
 		.family     = NFPROTO_IPV6,
-		.table      = "mangle",
-		.proto      = IPPROTO_TCP,
+		.checkentry = tcpoptstrip_tg_check,
 		.target     = tcpoptstrip_tg6,
 		.targetsize = sizeof(struct xt_tcpoptstrip_target_info),
 		.me         = THIS_MODULE,
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 1340c2f..bd43b59 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -59,27 +59,34 @@ tproxy_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return NF_DROP;
 }
 
-static bool tproxy_tg_check(const struct xt_tgchk_param *par)
+static unsigned int tproxy_tg_check(const struct xt_tgchk_param *par)
 {
-	const struct ipt_ip *i = par->entryinfo;
-
-	if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
-	    && !(i->invflags & IPT_INV_PROTO))
-		return true;
+	if (strcmp(par->table, "mangle") != 0) {
+		xt_compat_log(par, "TPROXY: can only be "
+			"called from \"mangle\" table, not \"%s\"",
+			par->table);
+		return XT_TPROXY_ERR_MANGLE_TABLE;
+	}
+	if ((par->hook_mask & ~(1 << NF_INET_PRE_ROUTING)) != 0) {
+		xt_compat_log(par, "TPROXY target can only be used in the "
+			      "PREROUTING chain.");
+		return XT_TPROXY_ERR_HOOKS_0;
+	}
+	if ((par->proto == IPPROTO_TCP || par->proto == IPPROTO_UDP)
+	    && !par->inverted)
+		return XT_TPROXY_ERR_NONE;
 
-	pr_info("xt_TPROXY: Can be used only in combination with "
-		"either -p tcp or -p udp\n");
-	return false;
+	xt_compat_log(par, "xt_TPROXY: Can be used only in combination with "
+		"either -p tcp or -p udp");
+	return XT_TPROXY_ERR_PROTO;
 }
 
 static struct xt_target tproxy_tg_reg __read_mostly = {
 	.name		= "TPROXY",
 	.family		= AF_INET,
-	.table		= "mangle",
 	.target		= tproxy_tg,
 	.targetsize	= sizeof(struct xt_tproxy_target_info),
 	.checkentry	= tproxy_tg_check,
-	.hooks		= 1 << NF_INET_PRE_ROUTING,
 	.me		= THIS_MODULE,
 };
 
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
index fbb04b8..3b19f91 100644
--- a/net/netfilter/xt_TRACE.c
+++ b/net/netfilter/xt_TRACE.c
@@ -4,6 +4,7 @@
 #include <linux/skbuff.h>
 
 #include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TRACE.h>
 
 MODULE_DESCRIPTION("Xtables: packet flow tracing");
 MODULE_LICENSE("GPL");
@@ -17,12 +18,23 @@ trace_tg(struct sk_buff *skb, const struct xt_target_param *par)
 	return XT_CONTINUE;
 }
 
+static unsigned int trace_tg_check(const struct xt_tgchk_param *par)
+{
+	if (strcmp(par->table, "raw") != 0) {
+		xt_compat_log(par, "TRACE: can only be "
+			"called from \"raw\" table, not \"%s\"",
+			par->table);
+		return XT_TRACE_ERR_RAW_TABLE;
+	}
+	return XT_TRACE_ERR_NONE;
+}
+
 static struct xt_target trace_tg_reg __read_mostly = {
 	.name       = "TRACE",
 	.revision   = 0,
 	.family     = NFPROTO_UNSPEC,
-	.table      = "raw",
 	.target     = trace_tg,
+	.checkentry = trace_tg_check,
 	.me         = THIS_MODULE,
 };
 
diff --git a/net/netfilter/xt_cluster.c b/net/netfilter/xt_cluster.c
index 69a639f..97397ab 100644
--- a/net/netfilter/xt_cluster.c
+++ b/net/netfilter/xt_cluster.c
@@ -131,22 +131,23 @@ xt_cluster_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	       !!(info->flags & XT_CLUSTER_F_INV);
 }
 
-static bool xt_cluster_mt_checkentry(const struct xt_mtchk_param *par)
+static unsigned int xt_cluster_mt_checkentry(const struct xt_mtchk_param *par)
 {
 	struct xt_cluster_match_info *info = par->matchinfo;
 
 	if (info->total_nodes > XT_CLUSTER_NODES_MAX) {
-		printk(KERN_ERR "xt_cluster: you have exceeded the maximum "
-				"number of cluster nodes (%u > %u)\n",
-				info->total_nodes, XT_CLUSTER_NODES_MAX);
-		return false;
+		info->total_nodes = XT_CLUSTER_NODES_MAX;
+		xt_compat_log(par, "xt_cluster: you have exceeded the maximum "
+			      "number of cluster nodes (%u > %u)",
+			      info->total_nodes, XT_CLUSTER_NODES_MAX);
+		return XT_CLUSTER_ERR_TOTAL_NODES;
 	}
 	if (info->node_mask >= (1ULL << info->total_nodes)) {
-		printk(KERN_ERR "xt_cluster: this node mask cannot be "
-				"higher than the total number of nodes\n");
-		return false;
+		xt_compat_log(par, "xt_cluster: this node mask cannot be "
+			      "higher than the total number of nodes");
+		return XT_CLUSTER_ERR_NODE_MASK;
 	}
-	return true;
+	return XT_CLUSTER_ERR_NONE;
 }
 
 static struct xt_match xt_cluster_match __read_mostly = {
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 955e659..5aeb176 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -92,27 +92,27 @@ connbytes_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 		return what >= sinfo->count.from;
 }
 
-static bool connbytes_mt_check(const struct xt_mtchk_param *par)
+static unsigned int connbytes_mt_check(const struct xt_mtchk_param *par)
 {
 	const struct xt_connbytes_info *sinfo = par->matchinfo;
 
 	if (sinfo->what != XT_CONNBYTES_PKTS &&
 	    sinfo->what != XT_CONNBYTES_BYTES &&
 	    sinfo->what != XT_CONNBYTES_AVGPKT)
-		return false;
+		return XT_CONNBYTES_ERR_WHAT;
 
 	if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
 	    sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
 	    sinfo->direction != XT_CONNBYTES_DIR_BOTH)
-		return false;
+		return XT_CONNBYTES_ERR_DIR;
 
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
-				    "proto=%u\n", par->family);
-		return false;
+		xt_compat_log(par, "can't load conntrack support for "
+			      "proto=%u", par->family);
+		return XT_CONNBYTES_ERR_CONNTRACK;
 	}
 
-	return true;
+	return XT_CONNBYTES_ERR_NONE;
 }
 
 static void connbytes_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 6809809..ae0fca8 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -223,29 +223,29 @@ connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return false;
 }
 
-static bool connlimit_mt_check(const struct xt_mtchk_param *par)
+static unsigned int connlimit_mt_check(const struct xt_mtchk_param *par)
 {
 	struct xt_connlimit_info *info = par->matchinfo;
 	unsigned int i;
 
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "cannot load conntrack support for "
-		       "address family %u\n", par->family);
-		return false;
+		xt_compat_log(par, "cannot load conntrack support for "
+			      "address family %u", par->family);
+		return XT_CONNLIMIT_ERR_CONNTRACK;
 	}
 
 	/* init private data */
 	info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
 	if (info->data == NULL) {
 		nf_ct_l3proto_module_put(par->family);
-		return false;
+		return XT_CONNLIMIT_ERR_INIT;
 	}
 
 	spin_lock_init(&info->data->lock);
 	for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i)
 		INIT_LIST_HEAD(&info->data->iphash[i]);
 
-	return true;
+	return XT_CONNLIMIT_ERR_NONE;
 }
 
 static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 86cacab..3f4d5bb 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -61,30 +61,30 @@ connmark_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
 	return ((ct->mark & info->mask) == info->mark) ^ info->invert;
 }
 
-static bool connmark_mt_check_v0(const struct xt_mtchk_param *par)
+static unsigned int connmark_mt_check_v0(const struct xt_mtchk_param *par)
 {
 	const struct xt_connmark_info *cm = par->matchinfo;
 
 	if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
-		printk(KERN_WARNING "connmark: only support 32bit mark\n");
-		return false;
+		xt_compat_log(par, "connmark: only support 32bit mark");
+		return XT_CONNMARK_ERR_32BIT_MARK;
 	}
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
-				    "proto=%u\n", par->family);
-		return false;
+		xt_compat_log(par, "can't load conntrack support for "
+			      "proto=%u", par->family);
+		return XT_CONNMARK_ERR_CONNTRACK;
 	}
-	return true;
+	return XT_CONNMARK_ERR_NONE;
 }
 
-static bool connmark_mt_check(const struct xt_mtchk_param *par)
+static unsigned int connmark_mt_check(const struct xt_mtchk_param *par)
 {
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "cannot load conntrack support for "
-		       "proto=%u\n", par->family);
-		return false;
+		xt_compat_log(par, "cannot load conntrack support for "
+			      "proto=%u", par->family);
+		return XT_CONNMARK_ERR_CONNTRACK;
 	}
-	return true;
+	return XT_CONNMARK_ERR_NONE;
 }
 
 static void connmark_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 0b7139f..5c541f9 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -278,14 +278,14 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return true;
 }
 
-static bool conntrack_mt_check(const struct xt_mtchk_param *par)
+static unsigned int conntrack_mt_check(const struct xt_mtchk_param *par)
 {
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
-				    "proto=%u\n", par->family);
-		return false;
+		xt_compat_log(par, "can't load conntrack support for "
+			      "proto=%u", par->family);
+		return XT_CONNTRACK_ERR_CONNTRACK;
 	}
-	return true;
+	return XT_CONNTRACK_ERR_NONE;
 }
 
 static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 0989f29..940e9f8 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -123,13 +123,22 @@ dccp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 			   XT_DCCP_OPTION, info->flags, info->invflags);
 }
 
-static bool dccp_mt_check(const struct xt_mtchk_param *par)
+static unsigned int dccp_mt_check(const struct xt_mtchk_param *par)
 {
-	const struct xt_dccp_info *info = par->matchinfo;
+	struct xt_dccp_info *info = par->matchinfo;
 
-	return !(info->flags & ~XT_DCCP_VALID_FLAGS)
-		&& !(info->invflags & ~XT_DCCP_VALID_FLAGS)
-		&& !(info->invflags & ~info->flags);
+	if (par->proto != IPPROTO_DCCP || par->inverted) {
+		xt_compat_log(par, "dccp match: only valid for protocol DCCP");
+		return XT_DCCP_ERR_PROTO;
+	}
+	if ((info->flags & ~XT_DCCP_VALID_FLAGS)
+	    || (info->invflags & ~XT_DCCP_VALID_FLAGS)) {
+	    	info->flags &= ~XT_DCCP_VALID_FLAGS;
+	    	info->invflags &= ~XT_DCCP_VALID_FLAGS;
+	    	return XT_DCCP_ERR_INVALID_FLAGS;
+	} else if (info->invflags & ~info->flags)
+	    	return XT_DCCP_ERR_FLAG_INVFLAG;
+	return XT_DCCP_ERR_NONE;
 }
 
 static struct xt_match dccp_mt_reg[] __read_mostly = {
@@ -139,7 +148,6 @@ static struct xt_match dccp_mt_reg[] __read_mostly = {
 		.checkentry	= dccp_mt_check,
 		.match		= dccp_mt,
 		.matchsize	= sizeof(struct xt_dccp_info),
-		.proto		= IPPROTO_DCCP,
 		.me 		= THIS_MODULE,
 	},
 	{
@@ -148,7 +156,6 @@ static struct xt_match dccp_mt_reg[] __read_mostly = {
 		.checkentry	= dccp_mt_check,
 		.match		= dccp_mt,
 		.matchsize	= sizeof(struct xt_dccp_info),
-		.proto		= IPPROTO_DCCP,
 		.me 		= THIS_MODULE,
 	},
 };
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index c3f8085..44cbbcb 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -43,16 +43,16 @@ dscp_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
 	return (dscp == info->dscp) ^ !!info->invert;
 }
 
-static bool dscp_mt_check(const struct xt_mtchk_param *par)
+static unsigned int dscp_mt_check(const struct xt_mtchk_param *par)
 {
 	const struct xt_dscp_info *info = par->matchinfo;
 
 	if (info->dscp > XT_DSCP_MAX) {
-		printk(KERN_ERR "xt_dscp: dscp %x out of range\n", info->dscp);
-		return false;
+		xt_compat_log(par, "xt_dscp: dscp %x out of range", info->dscp);
+		return XT_DSCP_ERR_RANGE;
 	}
 
-	return true;
+	return XT_DSCP_ERR_NONE;
 }
 
 static bool
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
index 6094399..b7adc2e 100644
--- a/net/netfilter/xt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -66,16 +66,21 @@ static bool esp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 			 !!(espinfo->invflags & XT_ESP_INV_SPI));
 }
 
-static bool esp_mt_check(const struct xt_mtchk_param *par)
+static unsigned int esp_mt_check(const struct xt_mtchk_param *par)
 {
-	const struct xt_esp *espinfo = par->matchinfo;
+	struct xt_esp *espinfo = par->matchinfo;
 
+	if (par->proto != IPPROTO_ESP || par->inverted) {
+		xt_compat_log(par, "esp match: only valid for protocol ESP");
+		return XT_ESP_ERR_PROTO;
+	}
 	if (espinfo->invflags & ~XT_ESP_INV_MASK) {
-		duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
-		return false;
+		duprintf("xt_esp: unknown flags %X", espinfo->invflags);
+		espinfo->invflags &= ~XT_ESP_INV_MASK;
+		return XT_ESP_ERR_FLAGS;
 	}
 
-	return true;
+	return XT_ESP_ERR_NONE;
 }
 
 static struct xt_match esp_mt_reg[] __read_mostly = {
@@ -85,7 +90,6 @@ static struct xt_match esp_mt_reg[] __read_mostly = {
 		.checkentry	= esp_mt_check,
 		.match		= esp_mt,
 		.matchsize	= sizeof(struct xt_esp),
-		.proto		= IPPROTO_ESP,
 		.me		= THIS_MODULE,
 	},
 	{
@@ -94,7 +98,6 @@ static struct xt_match esp_mt_reg[] __read_mostly = {
 		.checkentry	= esp_mt_check,
 		.match		= esp_mt,
 		.matchsize	= sizeof(struct xt_esp),
-		.proto		= IPPROTO_ESP,
 		.me		= THIS_MODULE,
 	},
 };
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 219dcdb..476ed53 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -663,29 +663,31 @@ hashlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return false;
 }
 
-static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
+static unsigned int hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
 {
 	struct xt_hashlimit_info *r = par->matchinfo;
 
 	/* Check for overflow. */
 	if (r->cfg.burst == 0 ||
 	    user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) {
-		printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
+		xt_compat_log(par, "xt_hashlimit: overflow, try lower: %u/%u",
 		       r->cfg.avg, r->cfg.burst);
-		return false;
+		return XT_HASHLIMIT_ERR_OVERFLOW;
 	}
 	if (r->cfg.mode == 0 ||
 	    r->cfg.mode > (XT_HASHLIMIT_HASH_DPT |
 			   XT_HASHLIMIT_HASH_DIP |
 			   XT_HASHLIMIT_HASH_SIP |
 			   XT_HASHLIMIT_HASH_SPT))
-		return false;
+		return XT_HASHLIMIT_ERR_MODE;
 	if (!r->cfg.gc_interval)
-		return false;
+		return XT_HASHLIMIT_ERR_INTERVAL;
 	if (!r->cfg.expire)
-		return false;
-	if (r->name[sizeof(r->name) - 1] != '\0')
-		return false;
+		return XT_HASHLIMIT_ERR_EXPIRE;
+	if (r->name[sizeof(r->name) - 1] != '\0') {
+		r->name[sizeof(r->name) - 1] = '\0';
+		return XT_HASHLIMIT_ERR_NAMELEN;
+	}
 
 	/* This is the best we've got: We cannot release and re-grab lock,
 	 * since checkentry() is called before x_tables.c grabs xt_mutex.
@@ -697,14 +699,14 @@ static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
 	r->hinfo = htable_find_get(r->name, par->match->family);
 	if (!r->hinfo && htable_create_v0(r, par->match->family) != 0) {
 		mutex_unlock(&hlimit_mutex);
-		return false;
+		return XT_HASHLIMIT_ERR_INIT;
 	}
 	mutex_unlock(&hlimit_mutex);
 
-	return true;
+	return XT_HASHLIMIT_ERR_NONE;
 }
 
-static bool hashlimit_mt_check(const struct xt_mtchk_param *par)
+static unsigned int hashlimit_mt_check(const struct xt_mtchk_param *par)
 {
 	struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
 
@@ -712,20 +714,20 @@ static bool hashlimit_mt_check(const struct xt_mtchk_param *par)
 	if (info->cfg.burst == 0 ||
 	    user2credits(info->cfg.avg * info->cfg.burst) <
 	    user2credits(info->cfg.avg)) {
-		printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
+		xt_compat_log(par, "xt_hashlimit: overflow, try lower: %u/%u",
 		       info->cfg.avg, info->cfg.burst);
-		return false;
+		return XT_HASHLIMIT_ERR_OVERFLOW;
 	}
 	if (info->cfg.gc_interval == 0 || info->cfg.expire == 0)
-		return false;
+		return XT_HASHLIMIT_ERR_INTERVAL;
 	if (info->name[sizeof(info->name)-1] != '\0')
-		return false;
+		return XT_HASHLIMIT_ERR_NAMELEN;
 	if (par->match->family == NFPROTO_IPV4) {
 		if (info->cfg.srcmask > 32 || info->cfg.dstmask > 32)
-			return false;
+			return XT_HASHLIMIT_ERR_NETMASK;
 	} else {
 		if (info->cfg.srcmask > 128 || info->cfg.dstmask > 128)
-			return false;
+			return XT_HASHLIMIT_ERR_NETMASK;
 	}
 
 	/* This is the best we've got: We cannot release and re-grab lock,
@@ -738,10 +740,10 @@ static bool hashlimit_mt_check(const struct xt_mtchk_param *par)
 	info->hinfo = htable_find_get(info->name, par->match->family);
 	if (!info->hinfo && htable_create(info, par->match->family) != 0) {
 		mutex_unlock(&hlimit_mutex);
-		return false;
+		return XT_HASHLIMIT_ERR_INIT;
 	}
 	mutex_unlock(&hlimit_mutex);
-	return true;
+	return XT_HASHLIMIT_ERR_NONE;
 }
 
 static void
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 64fc7f2..9dd2f6d 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -54,17 +54,17 @@ helper_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return ret;
 }
 
-static bool helper_mt_check(const struct xt_mtchk_param *par)
+static unsigned int helper_mt_check(const struct xt_mtchk_param *par)
 {
 	struct xt_helper_info *info = par->matchinfo;
 
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
-				    "proto=%u\n", par->family);
-		return false;
+		xt_compat_log(par, "can't load conntrack support for "
+			      "proto=%u", par->family);
+		return XT_HELPER_ERR_CONNTRACK;
 	}
 	info->name[29] = '\0';
-	return true;
+	return XT_HELPER_ERR_NONE;
 }
 
 static void helper_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 2e8089e..09fa7be 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -97,7 +97,7 @@ user2credits(u_int32_t user)
 	return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE;
 }
 
-static bool limit_mt_check(const struct xt_mtchk_param *par)
+static unsigned int limit_mt_check(const struct xt_mtchk_param *par)
 {
 	struct xt_rateinfo *r = par->matchinfo;
 	struct xt_limit_priv *priv;
@@ -105,14 +105,14 @@ static bool limit_mt_check(const struct xt_mtchk_param *par)
 	/* Check for overflow. */
 	if (r->burst == 0
 	    || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
-		printk("Overflow in xt_limit, try lower: %u/%u\n",
+		xt_compat_log(par, "Overflow in xt_limit, try lower: %u/%u",
 		       r->avg, r->burst);
-		return false;
+		return XT_LIMIT_ERR_OVERFLOW;
 	}
 
 	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
 	if (priv == NULL)
-		return -ENOMEM;
+		return XT_LIMIT_ERR_ALLOC;
 
 	/* For SMP, we only want to use one set of state. */
 	r->master = priv;
@@ -124,7 +124,7 @@ static bool limit_mt_check(const struct xt_mtchk_param *par)
 		r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
 		r->cost = user2credits(r->avg);
 	}
-	return true;
+	return XT_LIMIT_ERR_NONE;
 }
 
 static void limit_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index c200711..fee1271 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -36,14 +36,29 @@ static bool mac_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 		^ info->invert);
 }
 
+static unsigned int
+mac_mt_check(const struct xt_mtchk_param *par)
+{
+	unsigned int valid_hooks = (1 << NF_INET_PRE_ROUTING) | 
+		(1 << NF_INET_LOCAL_IN) |
+		(1 << NF_INET_FORWARD);
+
+	if ((par->hook_mask & ~valid_hooks) != 0) {
+		xt_compat_log(par, "mac match can only be used in the "
+			      "PREROUTING, INPUT and FORWARD chains.");
+		return XT_MAC_ERR_HOOKS_012;
+	}
+
+	return XT_MAC_ERR_NONE;
+}
+
 static struct xt_match mac_mt_reg __read_mostly = {
 	.name      = "mac",
 	.revision  = 0,
 	.family    = NFPROTO_UNSPEC,
 	.match     = mac_mt,
 	.matchsize = sizeof(struct xt_mac_info),
-	.hooks     = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) |
-	             (1 << NF_INET_FORWARD),
+	.checkentry = mac_mt_check,
 	.me        = THIS_MODULE,
 };
 
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 10b9e34..6180478 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -38,15 +38,15 @@ mark_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return ((skb->mark & info->mask) == info->mark) ^ info->invert;
 }
 
-static bool mark_mt_check_v0(const struct xt_mtchk_param *par)
+static unsigned int mark_mt_check_v0(const struct xt_mtchk_param *par)
 {
 	const struct xt_mark_info *minfo = par->matchinfo;
 
 	if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
-		printk(KERN_WARNING "mark: only supports 32bit mark\n");
-		return false;
+		xt_compat_log(par, "mark: only supports 32bit mark");
+		return XT_MARK_ERR_32BIT_MARK;
 	}
-	return true;
+	return XT_MARK_ERR_NONE;
 }
 
 #ifdef CONFIG_COMPAT
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index d06bb2d..eec9c98 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -141,56 +141,43 @@ multiport_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
-static inline bool
+static unsigned int
 check(u_int16_t proto,
-      u_int8_t ip_invflags,
+      bool inverted,
       u_int8_t match_flags,
       u_int8_t count)
 {
 	/* Must specify supported protocol, no unknown flags or bad count */
-	return (proto == IPPROTO_TCP || proto == IPPROTO_UDP
-		|| proto == IPPROTO_UDPLITE
-		|| proto == IPPROTO_SCTP || proto == IPPROTO_DCCP)
-		&& !(ip_invflags & XT_INV_PROTO)
-		&& (match_flags == XT_MULTIPORT_SOURCE
-		    || match_flags == XT_MULTIPORT_DESTINATION
-		    || match_flags == XT_MULTIPORT_EITHER)
-		&& count <= XT_MULTI_PORTS;
+	if (!(proto == IPPROTO_TCP
+	      || proto == IPPROTO_UDP || proto == IPPROTO_UDPLITE
+	      || proto == IPPROTO_SCTP
+	      || proto == IPPROTO_DCCP))
+	      	return XT_MULTIPORT_ERR_PROTO;
+	else if (inverted)
+		return XT_MULTIPORT_ERR_INV_PROTO;
+	else if (!(match_flags == XT_MULTIPORT_SOURCE
+		   || match_flags == XT_MULTIPORT_DESTINATION
+		   || match_flags == XT_MULTIPORT_EITHER))
+		return XT_MULTIPORT_ERR_FLAGS;
+	else if (count > XT_MULTI_PORTS)
+		return XT_MULTIPORT_ERR_COUNT;
+	
+	return XT_MULTIPORT_ERR_NONE;
 }
 
-static bool multiport_mt_check_v0(const struct xt_mtchk_param *par)
+static unsigned int multiport_mt_check_v0(const struct xt_mtchk_param *par)
 {
-	const struct ipt_ip *ip = par->entryinfo;
 	const struct xt_multiport *multiinfo = par->matchinfo;
 
-	return check(ip->proto, ip->invflags, multiinfo->flags,
+	return check(par->proto, par->inverted, multiinfo->flags,
 		     multiinfo->count);
 }
 
-static bool multiport_mt_check(const struct xt_mtchk_param *par)
+static unsigned int multiport_mt_check(const struct xt_mtchk_param *par)
 {
-	const struct ipt_ip *ip = par->entryinfo;
 	const struct xt_multiport_v1 *multiinfo = par->matchinfo;
 
-	return check(ip->proto, ip->invflags, multiinfo->flags,
-		     multiinfo->count);
-}
-
-static bool multiport_mt6_check_v0(const struct xt_mtchk_param *par)
-{
-	const struct ip6t_ip6 *ip = par->entryinfo;
-	const struct xt_multiport *multiinfo = par->matchinfo;
-
-	return check(ip->proto, ip->invflags, multiinfo->flags,
-		     multiinfo->count);
-}
-
-static bool multiport_mt6_check(const struct xt_mtchk_param *par)
-{
-	const struct ip6t_ip6 *ip = par->entryinfo;
-	const struct xt_multiport_v1 *multiinfo = par->matchinfo;
-
-	return check(ip->proto, ip->invflags, multiinfo->flags,
+	return check(par->proto, par->inverted, multiinfo->flags,
 		     multiinfo->count);
 }
 
@@ -217,7 +204,7 @@ static struct xt_match multiport_mt_reg[] __read_mostly = {
 		.name		= "multiport",
 		.family		= NFPROTO_IPV6,
 		.revision	= 0,
-		.checkentry	= multiport_mt6_check_v0,
+		.checkentry	= multiport_mt_check_v0,
 		.match		= multiport_mt_v0,
 		.matchsize	= sizeof(struct xt_multiport),
 		.me		= THIS_MODULE,
@@ -226,7 +213,7 @@ static struct xt_match multiport_mt_reg[] __read_mostly = {
 		.name		= "multiport",
 		.family		= NFPROTO_IPV6,
 		.revision	= 1,
-		.checkentry	= multiport_mt6_check,
+		.checkentry	= multiport_mt_check,
 		.match		= multiport_mt,
 		.matchsize	= sizeof(struct xt_multiport_v1),
 		.me		= THIS_MODULE,
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index 863e409..075dd54 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -356,16 +356,31 @@ static bool xt_osf_match_packet(const struct sk_buff *skb,
 	return fmatch == FMATCH_OK;
 }
 
+static unsigned int xt_osf_match_check(const struct xt_mtchk_param *par)
+{
+	unsigned int valid_hooks = (1 << NF_INET_LOCAL_IN) |
+		(1 << NF_INET_PRE_ROUTING) |
+		(1 << NF_INET_FORWARD);
+
+	if ((par->hook_mask & ~valid_hooks) != 0) {
+		xt_compat_log(par, "osf match can only be used in the "
+			      "INPUT, PREROUTING and FORWARD chains.");
+		return XT_OSF_ERR_HOOKS_012;
+	}
+	if (par->proto != IPPROTO_TCP || par->inverted) {
+		xt_compat_log(par, "osf match invalid for non-tcp packets");
+		return XT_OSF_ERR_NOT_TCP;
+	}
+	return XT_OSF_ERR_NONE;
+}
+
 static struct xt_match xt_osf_match = {
 	.name 		= "osf",
 	.revision	= 0,
 	.family		= NFPROTO_IPV4,
-	.proto		= IPPROTO_TCP,
-	.hooks      	= (1 << NF_INET_LOCAL_IN) |
-				(1 << NF_INET_PRE_ROUTING) |
-				(1 << NF_INET_FORWARD),
 	.match 		= xt_osf_match_packet,
 	.matchsize	= sizeof(struct xt_osf_info),
+	.checkentry	= xt_osf_match_check,
 	.me		= THIS_MODULE,
 };
 
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c
index 22b2a5e..32fe7c5 100644
--- a/net/netfilter/xt_owner.c
+++ b/net/netfilter/xt_owner.c
@@ -107,31 +107,47 @@ owner_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return true;
 }
 
-static bool owner_mt_check_v0(const struct xt_mtchk_param *par)
+static unsigned int owner_mt_check_v0(const struct xt_mtchk_param *par)
 {
 	const struct ipt_owner_info *info = par->matchinfo;
+	unsigned int valid_hooks = (1 << NF_INET_LOCAL_OUT) |
+		(1 << NF_INET_POST_ROUTING);
+
+	if ((par->hook_mask & ~valid_hooks) != 0) {
+		xt_compat_log(par, "owner match can only be used in the "
+			      "OUTPUT and POSTROUTING chains.");
+		return XT_OWNER_ERR_HOOKS_34;
+	}
 
 	if (info->match & (IPT_OWNER_PID | IPT_OWNER_SID | IPT_OWNER_COMM)) {
-		printk(KERN_WARNING KBUILD_MODNAME
+		xt_compat_log(par, KBUILD_MODNAME
 		       ": PID, SID and command matching is not "
-		       "supported anymore\n");
-		return false;
+		       "supported anymore");
+		return XT_OWNER_ERR_UNSUPPORTED;
 	}
 
-	return true;
+	return XT_OWNER_ERR_NONE;
 }
 
-static bool owner_mt6_check_v0(const struct xt_mtchk_param *par)
+static unsigned int owner_mt6_check_v0(const struct xt_mtchk_param *par)
 {
 	const struct ip6t_owner_info *info = par->matchinfo;
+	unsigned int valid_hooks = (1 << NF_INET_LOCAL_OUT) |
+		(1 << NF_INET_POST_ROUTING);
+
+	if ((par->hook_mask & ~valid_hooks) != 0) {
+		xt_compat_log(par, "owner match can only be used in the "
+			      "OUTPUT and POSTROUTING chains.");
+		return XT_OWNER_ERR_HOOKS_34;
+	}
 
 	if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) {
-		printk(KERN_WARNING KBUILD_MODNAME
-		       ": PID and SID matching is not supported anymore\n");
-		return false;
+		xt_compat_log(par, KBUILD_MODNAME
+		       ": PID and SID matching is not supported anymore");
+		return XT_OWNER_ERR_UNSUPPORTED;
 	}
 
-	return true;
+	return XT_OWNER_ERR_NONE;
 }
 
 static struct xt_match owner_mt_reg[] __read_mostly = {
@@ -142,8 +158,6 @@ static struct xt_match owner_mt_reg[] __read_mostly = {
 		.match      = owner_mt_v0,
 		.matchsize  = sizeof(struct ipt_owner_info),
 		.checkentry = owner_mt_check_v0,
-		.hooks      = (1 << NF_INET_LOCAL_OUT) |
-		              (1 << NF_INET_POST_ROUTING),
 		.me         = THIS_MODULE,
 	},
 	{
@@ -153,8 +167,6 @@ static struct xt_match owner_mt_reg[] __read_mostly = {
 		.match      = owner_mt6_v0,
 		.matchsize  = sizeof(struct ip6t_owner_info),
 		.checkentry = owner_mt6_check_v0,
-		.hooks      = (1 << NF_INET_LOCAL_OUT) |
-		              (1 << NF_INET_POST_ROUTING),
 		.me         = THIS_MODULE,
 	},
 	{
@@ -163,8 +175,6 @@ static struct xt_match owner_mt_reg[] __read_mostly = {
 		.family     = NFPROTO_UNSPEC,
 		.match      = owner_mt,
 		.matchsize  = sizeof(struct xt_owner_match_info),
-		.hooks      = (1 << NF_INET_LOCAL_OUT) |
-		              (1 << NF_INET_POST_ROUTING),
 		.me         = THIS_MODULE,
 	},
 };
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 8d28ca5..e3f5a74 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -83,25 +83,28 @@ match_outdev:
 	return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT));
 }
 
-static bool physdev_mt_check(const struct xt_mtchk_param *par)
+static unsigned int physdev_mt_check(const struct xt_mtchk_param *par)
 {
 	const struct xt_physdev_info *info = par->matchinfo;
 
-	if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
-	    info->bitmask & ~XT_PHYSDEV_OP_MASK)
-		return false;
+	if (!(info->bitmask & XT_PHYSDEV_OP_MASK))
+		return XT_PHYSDEV_ERR_MASK;
+	else if (info->bitmask & ~XT_PHYSDEV_OP_MASK) {
+		info->bitmask &= ~XT_PHYSDEV_OP_MASK;
+		return XT_PHYSDEV_ERR_UNKNOWN;
+	}
 	if (info->bitmask & XT_PHYSDEV_OP_OUT &&
 	    (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
 	     info->invert & XT_PHYSDEV_OP_BRIDGED) &&
 	    par->hook_mask & ((1 << NF_INET_LOCAL_OUT) |
 	    (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) {
-		printk(KERN_WARNING "physdev match: using --physdev-out in the "
+		xt_compat_log(par, "physdev match: using --physdev-out in the "
 		       "OUTPUT, FORWARD and POSTROUTING chains for non-bridged "
-		       "traffic is not supported anymore.\n");
+		       "traffic is not supported anymore.");
 		if (par->hook_mask & (1 << NF_INET_LOCAL_OUT))
-			return false;
+			return XT_PHYSDEV_ERR_UNSUPPORTED_HOOKS_234;
 	}
-	return true;
+	return XT_PHYSDEV_ERR_NONE;
 }
 
 static struct xt_match physdev_mt_reg __read_mostly = {
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 4cbfebd..7e81dc3 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -128,32 +128,32 @@ policy_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return ret;
 }
 
-static bool policy_mt_check(const struct xt_mtchk_param *par)
+static unsigned int policy_mt_check(const struct xt_mtchk_param *par)
 {
 	const struct xt_policy_info *info = par->matchinfo;
 
 	if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
-		printk(KERN_ERR "xt_policy: neither incoming nor "
-				"outgoing policy selected\n");
-		return false;
+		xt_compat_log(par, "xt_policy: neither incoming nor "
+			      "outgoing policy selected");
+		return XT_POLICY_ERR_FLAGS;
 	}
 	if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
 	    (1 << NF_INET_LOCAL_IN)) && info->flags & XT_POLICY_MATCH_OUT) {
-		printk(KERN_ERR "xt_policy: output policy not valid in "
-				"PRE_ROUTING and INPUT\n");
-		return false;
+		xt_compat_log(par, "xt_policy: output policy not valid in "
+			      "PREROUTING and INPUT chains");
+		return XT_POLICY_ERR_INVALID_OUTPUT_HOOKS_01;
 	}
 	if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
 	    (1 << NF_INET_LOCAL_OUT)) && info->flags & XT_POLICY_MATCH_IN) {
-		printk(KERN_ERR "xt_policy: input policy not valid in "
-				"POST_ROUTING and OUTPUT\n");
-		return false;
+		xt_compat_log(par, "xt_policy: input policy not valid in "
+			      "POSTROUTING and OUTPUT chains");
+		return XT_POLICY_ERR_INVALID_INPUT_HOOKS_34;
 	}
 	if (info->len > XT_POLICY_MAX_ELEM) {
-		printk(KERN_ERR "xt_policy: too many policy elements\n");
-		return false;
+		xt_compat_log(par, "xt_policy: too many policy elements");
+		return XT_POLICY_ERR_MAX_ELEM;
 	}
-	return true;
+	return XT_POLICY_ERR_NONE;
 }
 
 static struct xt_match policy_mt_reg[] __read_mostly = {
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
index 01dd07b..132610a 100644
--- a/net/netfilter/xt_quota.c
+++ b/net/netfilter/xt_quota.c
@@ -43,18 +43,20 @@ quota_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return ret;
 }
 
-static bool quota_mt_check(const struct xt_mtchk_param *par)
+static unsigned int quota_mt_check(const struct xt_mtchk_param *par)
 {
 	struct xt_quota_info *q = par->matchinfo;
 
-	if (q->flags & ~XT_QUOTA_MASK)
-		return false;
+	if (q->flags & ~XT_QUOTA_MASK) {
+		q->flags &= ~XT_QUOTA_MASK;
+		return XT_QUOTA_ERR_FLAGS;
+	}
 
 	q->master = kmalloc(sizeof(*q->master), GFP_KERNEL);
 	if (q->master == NULL)
-		return -ENOMEM;
+		return XT_QUOTA_ERR_ALLOC;
 
-	return true;
+	return XT_QUOTA_ERR_NONE;
 }
 
 static void quota_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c
index 220a1d5..aabcae6 100644
--- a/net/netfilter/xt_rateest.c
+++ b/net/netfilter/xt_rateest.c
@@ -74,17 +74,22 @@ xt_rateest_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return ret;
 }
 
-static bool xt_rateest_mt_checkentry(const struct xt_mtchk_param *par)
+static unsigned int xt_rateest_mt_checkentry(const struct xt_mtchk_param *par)
 {
 	struct xt_rateest_match_info *info = par->matchinfo;
 	struct xt_rateest *est1, *est2;
+	unsigned int ret = XT_RATEEST_ERR_NONE;
 
 	if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
-				     XT_RATEEST_MATCH_REL)) != 1)
+				     XT_RATEEST_MATCH_REL)) != 1) {
+		ret = XT_RATEEST_ERR_ABS;
 		goto err1;
+	}
 
-	if (!(info->flags & (XT_RATEEST_MATCH_BPS | XT_RATEEST_MATCH_PPS)))
+	if (!(info->flags & (XT_RATEEST_MATCH_BPS | XT_RATEEST_MATCH_PPS))) {
+		ret = XT_RATEEST_ERR_BPS;
 		goto err1;
+	}
 
 	switch (info->mode) {
 	case XT_RATEEST_MATCH_EQ:
@@ -92,29 +97,34 @@ static bool xt_rateest_mt_checkentry(const struct xt_mtchk_param *par)
 	case XT_RATEEST_MATCH_GT:
 		break;
 	default:
+		ret = XT_RATEEST_ERR_MODE;
 		goto err1;
 	}
 
 	est1 = xt_rateest_lookup(info->name1);
-	if (!est1)
+	if (!est1) {
+		ret = XT_RATEEST_ERR_NAME1;
 		goto err1;
+	}
 
 	if (info->flags & XT_RATEEST_MATCH_REL) {
 		est2 = xt_rateest_lookup(info->name2);
-		if (!est2)
+		if (!est2) {
+			ret = XT_RATEEST_ERR_NAME2;
 			goto err2;
+		}
 	} else
 		est2 = NULL;
 
 
 	info->est1 = est1;
 	info->est2 = est2;
-	return true;
+	return XT_RATEEST_ERR_NONE;
 
 err2:
 	xt_rateest_put(est1);
 err1:
-	return false;
+	return ret;
 }
 
 static void xt_rateest_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index 484d168..ad459b8 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -30,12 +30,26 @@ realm_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
 }
 
+static unsigned int realm_mt_check(const struct xt_mtchk_param *par)
+{
+	unsigned int valid_hooks = (1 << NF_INET_POST_ROUTING) |
+		(1 << NF_INET_FORWARD) |
+		(1 << NF_INET_LOCAL_OUT) |
+		(1 << NF_INET_LOCAL_IN);
+
+	if ((par->hook_mask & ~valid_hooks) != 0) {
+		xt_compat_log(par, "realm match can only be used in the "
+			      "POSTROUTING, FORWARD, INPUT and OUTPUT chains.");
+		return XT_REALM_ERR_HOOKS_1234;
+	}
+	return XT_REALM_ERR_NONE;
+}
+
 static struct xt_match realm_mt_reg __read_mostly = {
 	.name		= "realm",
 	.match		= realm_mt,
 	.matchsize	= sizeof(struct xt_realm_info),
-	.hooks		= (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_FORWARD) |
-			  (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_LOCAL_IN),
+	.checkentry	= realm_mt_check,
 	.family		= NFPROTO_UNSPEC,
 	.me		= THIS_MODULE
 };
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index eb0ceb8..51bbad1 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -277,41 +277,45 @@ out:
 	return ret;
 }
 
-static bool recent_mt_check(const struct xt_mtchk_param *par)
+static unsigned int recent_mt_check(const struct xt_mtchk_param *par)
 {
-	const struct xt_recent_mtinfo *info = par->matchinfo;
+	struct xt_recent_mtinfo *info = par->matchinfo;
 	struct recent_table *t;
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *pde;
 #endif
 	unsigned i;
-	bool ret = false;
+	unsigned int ret = XT_RECENT_ERR_NONE;
 
 	if (hweight8(info->check_set &
 		     (XT_RECENT_SET | XT_RECENT_REMOVE |
 		      XT_RECENT_CHECK | XT_RECENT_UPDATE)) != 1)
-		return false;
+		return XT_RECENT_ERR_CHECK_SET;
 	if ((info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE)) &&
 	    (info->seconds || info->hit_count))
-		return false;
-	if (info->hit_count > ip_pkt_list_tot)
-		return false;
+		return XT_RECENT_ERR_SET;
+	if (info->hit_count > ip_pkt_list_tot) {
+		info->hit_count = ip_pkt_list_tot;
+		return XT_RECENT_ERR_HIT_COUNT;
+	}
 	if (info->name[0] == '\0' ||
 	    strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN)
-		return false;
+		return XT_RECENT_ERR_NAME;
 
 	mutex_lock(&recent_mutex);
 	t = recent_table_lookup(info->name);
 	if (t != NULL) {
 		t->refcnt++;
-		ret = true;
+		ret = XT_RECENT_ERR_NONE;
 		goto out;
 	}
 
 	t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
 		    GFP_KERNEL);
-	if (t == NULL)
+	if (t == NULL) {
+		ret = XT_RECENT_ERR_ALLOC;
 		goto out;
+	}
 	t->refcnt = 1;
 	strcpy(t->name, info->name);
 	INIT_LIST_HEAD(&t->lru_list);
@@ -322,6 +326,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
 		  &recent_mt_fops, t);
 	if (pde == NULL) {
 		kfree(t);
+		ret = XT_RECENT_ERR_PROC;
 		goto out;
 	}
 	pde->uid = ip_list_uid;
@@ -332,6 +337,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
 	if (pde == NULL) {
 		remove_proc_entry(t->name, proc_old_dir);
 		kfree(t);
+		ret = XT_RECENT_ERR_PROC_ENTRY;
 		goto out;
 	}
 	pde->uid = ip_list_uid;
@@ -341,7 +347,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
 	spin_lock_bh(&recent_lock);
 	list_add_tail(&t->list, &tables);
 	spin_unlock_bh(&recent_lock);
-	ret = true;
+	ret = XT_RECENT_ERR_NONE;
 out:
 	mutex_unlock(&recent_mutex);
 	return ret;
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index a189ada..abe28c3 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -147,18 +147,28 @@ sctp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 			   XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
 }
 
-static bool sctp_mt_check(const struct xt_mtchk_param *par)
+static unsigned int sctp_mt_check(const struct xt_mtchk_param *par)
 {
-	const struct xt_sctp_info *info = par->matchinfo;
+	struct xt_sctp_info *info = par->matchinfo;
 
-	return !(info->flags & ~XT_SCTP_VALID_FLAGS)
-		&& !(info->invflags & ~XT_SCTP_VALID_FLAGS)
-		&& !(info->invflags & ~info->flags)
-		&& ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
-			(info->chunk_match_type &
-				(SCTP_CHUNK_MATCH_ALL
-				| SCTP_CHUNK_MATCH_ANY
-				| SCTP_CHUNK_MATCH_ONLY)));
+	if (par->proto != IPPROTO_SCTP || par->inverted) {
+		xt_compat_log(par, "sctp match: only valid for protocol SCTP");
+		return XT_SCTP_ERR_PROTO;
+	}
+	if ((info->flags & ~XT_SCTP_VALID_FLAGS)
+	    || (info->invflags & ~XT_SCTP_VALID_FLAGS)) {
+	    	info->flags &= ~XT_SCTP_VALID_FLAGS;
+	    	info->invflags &= ~XT_SCTP_VALID_FLAGS;
+	    	return XT_SCTP_ERR_INVALID_FLAGS;
+	} else if (info->invflags & ~info->flags)
+	    	return XT_SCTP_ERR_FLAG_INVFLAG;
+	else if ((info->flags & XT_SCTP_CHUNK_TYPES) 
+		 && !(info->chunk_match_type &
+		      (SCTP_CHUNK_MATCH_ALL
+		       | SCTP_CHUNK_MATCH_ANY
+		       | SCTP_CHUNK_MATCH_ONLY)))
+		return XT_SCTP_ERR_CHUNK;
+	return XT_SCTP_ERR_NONE;
 }
 
 static struct xt_match sctp_mt_reg[] __read_mostly = {
@@ -168,7 +178,6 @@ static struct xt_match sctp_mt_reg[] __read_mostly = {
 		.checkentry	= sctp_mt_check,
 		.match		= sctp_mt,
 		.matchsize	= sizeof(struct xt_sctp_info),
-		.proto		= IPPROTO_SCTP,
 		.me		= THIS_MODULE
 	},
 	{
@@ -177,7 +186,6 @@ static struct xt_match sctp_mt_reg[] __read_mostly = {
 		.checkentry	= sctp_mt_check,
 		.match		= sctp_mt,
 		.matchsize	= sizeof(struct xt_sctp_info),
-		.proto		= IPPROTO_SCTP,
 		.me		= THIS_MODULE
 	},
 };
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index ebf00ad..7c90f2f 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -186,13 +186,25 @@ socket_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par)
 	return socket_match(skb, par, par->matchinfo);
 }
 
+static unsigned int socket_mt_check(const struct xt_mtchk_param *par)
+{
+	unsigned int valid_hooks = 1 << NF_INET_PRE_ROUTING;
+
+	if ((par->hook_mask & ~valid_hooks) != 0) {
+		xt_compat_log(par, "socket match can only be used in the "
+			      "PREROUTING chain.");
+		return XT_SOCKET_ERR_HOOKS_0;
+	}
+	return XT_SOCKET_ERR_NONE;
+}
+
 static struct xt_match socket_mt_reg[] __read_mostly = {
 	{
 		.name		= "socket",
 		.revision	= 0,
 		.family		= NFPROTO_IPV4,
 		.match		= socket_mt_v0,
-		.hooks		= 1 << NF_INET_PRE_ROUTING,
+		.checkentry	= socket_mt_check,
 		.me		= THIS_MODULE,
 	},
 	{
@@ -201,7 +213,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
 		.family		= NFPROTO_IPV4,
 		.match		= socket_mt_v1,
 		.matchsize	= sizeof(struct xt_socket_mtinfo1),
-		.hooks		= 1 << NF_INET_PRE_ROUTING,
+		.checkentry	= socket_mt_check,
 		.me		= THIS_MODULE,
 	},
 };
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index 4c946cb..fe013af 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -37,14 +37,14 @@ state_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return (sinfo->statemask & statebit);
 }
 
-static bool state_mt_check(const struct xt_mtchk_param *par)
+static unsigned int state_mt_check(const struct xt_mtchk_param *par)
 {
 	if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
-				    "proto=%u\n", par->match->family);
-		return false;
+		xt_compat_log(par, "can't load conntrack support for "
+			      "proto=%u", par->match->family);
+		return XT_STATE_ERR_CONNTRACK;
 	}
-	return true;
+	return XT_STATE_ERR_NONE;
 }
 
 static void state_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
index d8c0f8f..bae6280 100644
--- a/net/netfilter/xt_statistic.c
+++ b/net/netfilter/xt_statistic.c
@@ -52,22 +52,25 @@ statistic_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return ret;
 }
 
-static bool statistic_mt_check(const struct xt_mtchk_param *par)
+static unsigned int statistic_mt_check(const struct xt_mtchk_param *par)
 {
 	struct xt_statistic_info *info = par->matchinfo;
 
-	if (info->mode > XT_STATISTIC_MODE_MAX ||
-	    info->flags & ~XT_STATISTIC_MASK)
-		return false;
+	if (info->mode > XT_STATISTIC_MODE_MAX)
+		return XT_STATISTIC_ERR_MODE;
+	else if (info->flags & ~XT_STATISTIC_MASK) {
+	    	info->flags &= ~XT_STATISTIC_MASK;
+		return XT_STATISTIC_ERR_FLAGS;
+	}
 
 	info->master = kzalloc(sizeof(*info->master), GFP_KERNEL);
 	if (info->master == NULL) {
-		printk(KERN_ERR KBUILD_MODNAME ": Out of memory\n");
-		return false;
+		xt_compat_log(par, KBUILD_MODNAME ": Out of memory");
+		return XT_STATISTIC_ERR_ALLOC;
 	}
 	info->master->count = info->u.nth.count;
 
-	return true;
+	return XT_STATISTIC_ERR_NONE;
 }
 
 static void statistic_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index b4d7741..405db58 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -40,7 +40,7 @@ string_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 
 #define STRING_TEXT_PRIV(m) ((struct xt_string_info *)(m))
 
-static bool string_mt_check(const struct xt_mtchk_param *par)
+static unsigned int string_mt_check(const struct xt_mtchk_param *par)
 {
 	struct xt_string_info *conf = par->matchinfo;
 	struct ts_config *ts_conf;
@@ -48,26 +48,30 @@ static bool string_mt_check(const struct xt_mtchk_param *par)
 
 	/* Damn, can't handle this case properly with iptables... */
 	if (conf->from_offset > conf->to_offset)
-		return false;
-	if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0')
-		return false;
-	if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE)
-		return false;
+		return XT_STRING_ERR_OFFSET;
+	if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0') {
+		conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] = '\0';
+		return XT_STRING_ERR_ALGO_NAME;
+	}
+	if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE) {
+		conf->patlen = XT_STRING_MAX_PATTERN_SIZE;
+		return XT_STRING_ERR_PATLEN;
+	}
 	if (par->match->revision == 1) {
 		if (conf->u.v1.flags &
 		    ~(XT_STRING_FLAG_IGNORECASE | XT_STRING_FLAG_INVERT))
-			return false;
+			return XT_STRING_ERR_IGNORECASE;
 		if (conf->u.v1.flags & XT_STRING_FLAG_IGNORECASE)
 			flags |= TS_IGNORECASE;
 	}
 	ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
 				     GFP_KERNEL, flags);
 	if (IS_ERR(ts_conf))
-		return false;
+		return XT_STRING_ERR_PREPARE;
 
 	conf->config = ts_conf;
 
-	return true;
+	return XT_STRING_ERR_NONE;
 }
 
 static void string_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 4809b34..447ca08 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -77,13 +77,22 @@ dropit:
 	return false;
 }
 
+static unsigned int tcpmss_mt_check(const struct xt_mtchk_param *par)
+{
+	if (par->proto != IPPROTO_TCP || par->inverted) {
+		xt_compat_log(par, "tcpmss match: only valid for protocol TCP");
+		return XT_TCPMSS_ERR_PROTO;
+	}
+	return XT_TCPMSS_ERR_NONE;
+}
+
 static struct xt_match tcpmss_mt_reg[] __read_mostly = {
 	{
 		.name		= "tcpmss",
 		.family		= NFPROTO_IPV4,
 		.match		= tcpmss_mt,
 		.matchsize	= sizeof(struct xt_tcpmss_match_info),
-		.proto		= IPPROTO_TCP,
+		.checkentry	= tcpmss_mt_check,
 		.me		= THIS_MODULE,
 	},
 	{
@@ -91,7 +100,7 @@ static struct xt_match tcpmss_mt_reg[] __read_mostly = {
 		.family		= NFPROTO_IPV6,
 		.match		= tcpmss_mt,
 		.matchsize	= sizeof(struct xt_tcpmss_match_info),
-		.proto		= IPPROTO_TCP,
+		.checkentry	= tcpmss_mt_check,
 		.me		= THIS_MODULE,
 	},
 };
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 1ebdc49..72eb982 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -126,12 +126,20 @@ static bool tcp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return true;
 }
 
-static bool tcp_mt_check(const struct xt_mtchk_param *par)
+static unsigned int tcp_mt_check(const struct xt_mtchk_param *par)
 {
-	const struct xt_tcp *tcpinfo = par->matchinfo;
+	struct xt_tcp *tcpinfo = par->matchinfo;
 
+	if (par->proto != IPPROTO_TCP || par->inverted) {
+		xt_compat_log(par, "tcp match: only valid for protocol TCP");
+		return XT_TCPUDP_ERR_PROTO;
+	}
 	/* Must specify no unknown invflags */
-	return !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
+	if (tcpinfo->invflags & ~XT_TCP_INV_MASK) {
+		tcpinfo->invflags &= ~XT_TCP_INV_MASK;
+		return XT_TCPUDP_ERR_FLAGS;
+	}
+	return XT_TCPUDP_ERR_NONE;
 }
 
 static bool udp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
@@ -161,12 +169,36 @@ static bool udp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 			      !!(udpinfo->invflags & XT_UDP_INV_DSTPT));
 }
 
-static bool udp_mt_check(const struct xt_mtchk_param *par)
+static unsigned int udp_mt_check(const struct xt_mtchk_param *par)
 {
-	const struct xt_udp *udpinfo = par->matchinfo;
+	struct xt_udp *udpinfo = par->matchinfo;
 
+	if (par->proto != IPPROTO_UDP || par->inverted) {
+		xt_compat_log(par, "udp match: only valid for protocol UDP");
+		return XT_TCPUDP_ERR_PROTO;
+	}
 	/* Must specify no unknown invflags */
-	return !(udpinfo->invflags & ~XT_UDP_INV_MASK);
+	if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
+		udpinfo->invflags &= ~XT_UDP_INV_MASK;
+		return XT_TCPUDP_ERR_FLAGS;
+	}
+	return XT_TCPUDP_ERR_NONE;
+}
+
+static unsigned int udplite_mt_check(const struct xt_mtchk_param *par)
+{
+	struct xt_udp *udpinfo = par->matchinfo;
+
+	if (par->proto != IPPROTO_UDPLITE || par->inverted) {
+		xt_compat_log(par, "udplite match: only valid for protocol UDPLITE");
+		return XT_TCPUDP_ERR_PROTO;
+	}
+	/* Must specify no unknown invflags */
+	if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
+		udpinfo->invflags &= ~XT_UDP_INV_MASK;
+		return XT_TCPUDP_ERR_FLAGS;
+	}
+	return XT_TCPUDP_ERR_NONE;
 }
 
 static struct xt_match tcpudp_mt_reg[] __read_mostly = {
@@ -176,7 +208,6 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
 		.checkentry	= tcp_mt_check,
 		.match		= tcp_mt,
 		.matchsize	= sizeof(struct xt_tcp),
-		.proto		= IPPROTO_TCP,
 		.me		= THIS_MODULE,
 	},
 	{
@@ -185,7 +216,6 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
 		.checkentry	= tcp_mt_check,
 		.match		= tcp_mt,
 		.matchsize	= sizeof(struct xt_tcp),
-		.proto		= IPPROTO_TCP,
 		.me		= THIS_MODULE,
 	},
 	{
@@ -194,7 +224,6 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
 		.checkentry	= udp_mt_check,
 		.match		= udp_mt,
 		.matchsize	= sizeof(struct xt_udp),
-		.proto		= IPPROTO_UDP,
 		.me		= THIS_MODULE,
 	},
 	{
@@ -203,25 +232,22 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
 		.checkentry	= udp_mt_check,
 		.match		= udp_mt,
 		.matchsize	= sizeof(struct xt_udp),
-		.proto		= IPPROTO_UDP,
 		.me		= THIS_MODULE,
 	},
 	{
 		.name		= "udplite",
 		.family		= NFPROTO_IPV4,
-		.checkentry	= udp_mt_check,
+		.checkentry	= udplite_mt_check,
 		.match		= udp_mt,
 		.matchsize	= sizeof(struct xt_udp),
-		.proto		= IPPROTO_UDPLITE,
 		.me		= THIS_MODULE,
 	},
 	{
 		.name		= "udplite",
 		.family		= NFPROTO_IPV6,
-		.checkentry	= udp_mt_check,
+		.checkentry	= udplite_mt_check,
 		.match		= udp_mt,
 		.matchsize	= sizeof(struct xt_udp),
-		.proto		= IPPROTO_UDPLITE,
 		.me		= THIS_MODULE,
 	},
 };
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index 93acaa5..59f8375 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -218,18 +218,18 @@ time_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 	return true;
 }
 
-static bool time_mt_check(const struct xt_mtchk_param *par)
+static unsigned int time_mt_check(const struct xt_mtchk_param *par)
 {
 	const struct xt_time_info *info = par->matchinfo;
 
 	if (info->daytime_start > XT_TIME_MAX_DAYTIME ||
 	    info->daytime_stop > XT_TIME_MAX_DAYTIME) {
-		printk(KERN_WARNING "xt_time: invalid argument - start or "
-		       "stop time greater than 23:59:59\n");
-		return false;
+		xt_compat_log(par, "xt_time: invalid argument - start or "
+		       "stop time greater than 23:59:59");
+		return XT_TIME_ERR_INVALID;
 	}
 
-	return true;
+	return XT_TIME_ERR_NONE;
 }
 
 static struct xt_match xt_time_mt_reg __read_mostly = {


Best regards,
Jozsef
-
E-mail  : kadlec@xxxxxxxxxxxxxxxxx, kadlec@xxxxxxxxxxxx
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
          H-1525 Budapest 114, POB. 49, Hungary
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux