Topic: iptables and kernel CLASSIFY target support

I'm currently trying to put a somewhat more complex firewall setup on an OpenWRT based (WhiteRussianRC5) based device and for this I need the CLASSIFY target in iptables and the kernel.

In the thread http://forum.openwrt.org/viewtopic.php?id=1809 I found a discussion from January last year about this -- and bluesguy was kind enough to put online his ipt_CLASSIFY.o and libipt_CLASSIFY.so for kernel 2.4.30 and iptables 1.3.1 at http://blues.gotdns.org/ipt_classify.tar.bz

However, since WhiteRussianRC5 uses iptables 1.3.3, the iptables library does not work.

Given that I could also not find it in the backports, I had a look at the build instructions, but I have to admit that they are too sketchy for me to figure out what exactly I'd have to do -- and the information online seems at least partially contradictory. So I wonder:

   * Does anyone have an updated version of the CLASSIFY modules for WhiteRussianRC5? 

   * Given that the "tc" and "ip" packages along with the qdisk & imq support are all present in RC5 (very pleasant surprise, by the way. thanks a lot!), I wonder: Why is the CLASSIFY target not already included in WhiteRussianRC5? Are there plans for including it officially?

Any help greatly appreciated,

Best,
Georg

Re: iptables and kernel CLASSIFY target support

greve wrote:

* Given that the "tc" and "ip" packages along with the qdisk & imq support are all present in RC5 (very pleasant surprise, by the way. thanks a lot!), I wonder: Why is the CLASSIFY target not already included in WhiteRussianRC5? Are there plans for including it officially?

Couldn't you also use the MARK target with some tc filters?

Re: iptables and kernel CLASSIFY target support

No, MARK does not work for me for two reason:

a) MARK does not help to direct traffic inside a more complex qdisc setup, at least last time I checked it didn't.

b) I already need the entire MARK address space for other purposes, including to track certain kinds of traffic and to monitor which device something came in on so that you can use that information also in tables that have no "-i <device>" support for iptables.

So I really do need CLASSIFY, and it seems that it should not be very hard to also provide it along with all the other extra modules that are provided by OpenWRT already. It seems that the layer7 filters are much more complex to add, for instance. So I'd really appreciate if

* someone could provide me with the CLASSIFY modules in case they have them for WhiteRussian RC5

* the person maintaining iptables in OpenWRT could add the CLASSIFY support to WhiteRussian RC6, at least. smile

Re: iptables and kernel CLASSIFY target support

I just tried to figure out what would be needed to actually get CLASSIFY target support into OpenWRT, and it boils down to the following 2.4.30 kernel patch plus *enabling* CLASSIFY in iptables-1.3.3, because it is already included in the extras.

This is a comparatively small patch, and enabling CLASSIFY as one of the extras should not be a great burden to anybody, really.

Could some developer please do this in repository?

---------------- cut here --------------
diff -uprN linux-2.4.30.orig/Documentation/Configure.help linux-2.4.30/Documentation/Configure.help
--- linux-2.4.30.orig/Documentation/Configure.help    2006-08-08 19:29:58.000000000 +0200
+++ linux-2.4.30/Documentation/Configure.help    2006-08-08 19:46:37.000000000 +0200
@@ -3225,6 +3225,17 @@ CONFIG_IP_NF_TARGET_LOG
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.

+CLASSIFY target support
+CONFIG_IP_NF_TARGET_CLASSIFY
+  This option adds a `CLASSIFY' target, which enables the user to set
+  the priority of a packet. Some qdiscs can use this value for classification,
+  among these are:
+
+  atm, cbq, dsmark, pfifo_fast, htb, prio
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
TTL target support
CONFIG_IP_NF_TARGET_TTL
   This option adds a `TTL' target, which enables the user to set
diff -uprN linux-2.4.30.orig/include/linux/netfilter_ipv4/ipt_CLASSIFY.h linux-2.4.30/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
--- linux-2.4.30.orig/include/linux/netfilter_ipv4/ipt_CLASSIFY.h    1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.30/include/linux/netfilter_ipv4/ipt_CLASSIFY.h    2006-08-08 19:46:37.000000000 +0200
@@ -0,0 +1,8 @@
+#ifndef _IPT_CLASSIFY_H
+#define _IPT_CLASSIFY_H
+
+struct ipt_classify_target_info {
+    u_int32_t priority;
+};
+
+#endif /*_IPT_CLASSIFY_H */
diff -uprN linux-2.4.30.orig/net/ipv4/netfilter/Config.in linux-2.4.30/net/ipv4/netfilter/Config.in
--- linux-2.4.30.orig/net/ipv4/netfilter/Config.in    2006-08-08 19:29:37.000000000 +0200
+++ linux-2.4.30/net/ipv4/netfilter/Config.in    2006-08-08 19:46:37.000000000 +0200
@@ -147,6 +147,7 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ];
     dep_tristate '    DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
 
     dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+    dep_tristate '    CLASSIFY target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_CLASSIFY $CONFIG_IP_NF_MANGLE
     dep_tristate '    IMQ target support' CONFIG_IP_NF_TARGET_IMQ $CONFIG_IP_NF_MANGLE
   fi
   if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
diff -uprN linux-2.4.30.orig/net/ipv4/netfilter/ipt_CLASSIFY.c linux-2.4.30/net/ipv4/netfilter/ipt_CLASSIFY.c
--- linux-2.4.30.orig/net/ipv4/netfilter/ipt_CLASSIFY.c    1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.30/net/ipv4/netfilter/ipt_CLASSIFY.c    2006-08-08 19:46:37.000000000 +0200
@@ -0,0 +1,82 @@
+/*
+ * This is a module which is used for setting the skb->priority field
+ * of an skb for qdisc classification.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_CLASSIFY.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("iptables qdisc classification target module");
+
+static unsigned int
+target(struct sk_buff **pskb,
+       unsigned int hooknum,
+       const struct net_device *in,
+       const struct net_device *out,
+       const void *targinfo,
+       void *userinfo)
+{
+    const struct ipt_classify_target_info *clinfo = targinfo;
+
+    if((*pskb)->priority != clinfo->priority) {
+        (*pskb)->priority = clinfo->priority;
+        (*pskb)->nfcache |= NFC_ALTERED;
+    }
+
+    return IPT_CONTINUE;
+}
+
+static int
+checkentry(const char *tablename,
+           const struct ipt_entry *e,
+           void *targinfo,
+           unsigned int targinfosize,
+           unsigned int hook_mask)
+{
+    if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){
+        printk(KERN_ERR "CLASSIFY: invalid size (%u != %u).\n",
+               targinfosize,
+               IPT_ALIGN(sizeof(struct ipt_classify_target_info)));
+        return 0;
+    }
+   
+    if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
+        printk(KERN_ERR "CLASSIFY: only valid in POST_ROUTING.\n");
+        return 0;
+    }
+
+    if (strcmp(tablename, "mangle") != 0) {
+        printk(KERN_WARNING "CLASSIFY: can only be called from "
+                            "\"mangle\" table, not \"%s\".\n",
+                            tablename);
+        return 0;
+    }
+
+    return 1;
+}
+
+static struct ipt_target ipt_classify_reg
+= { { NULL, NULL }, "CLASSIFY", target, checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+    if (ipt_register_target(&ipt_classify_reg))
+        return -EINVAL;
+
+    return 0;
+}
+
+static void __exit fini(void)
+{
+    ipt_unregister_target(&ipt_classify_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff -uprN linux-2.4.30.orig/net/ipv4/netfilter/Makefile linux-2.4.30/net/ipv4/netfilter/Makefile
--- linux-2.4.30.orig/net/ipv4/netfilter/Makefile    2006-08-08 19:29:37.000000000 +0200
+++ linux-2.4.30/net/ipv4/netfilter/Makefile    2006-08-08 19:46:37.000000000 +0200
@@ -114,6 +114,7 @@ obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt

# targets
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
+obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
obj-$(CONFIG_IP_NF_TARGET_MIRROR) += ipt_MIRROR.o
obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
---------------- cut here --------------

Re: iptables and kernel CLASSIFY target support

As Wiki markup on dev.openwrt.org does not permit putting it there by cut & past and I don't see an "attach file" button, here is the patch for kernel 2.4.32. Simply copy into target/linux/generic-2.4/patches/ as 619-iptables_classify.patch or so.

--------------- snip --------------
diff -uprN linux-2.4.32.reference/Documentation/Configure.help linux-2.4.32/Documentation/Configure.help
--- linux-2.4.32.reference/Documentation/Configure.help    2006-08-17 12:28:35.000000000 +0200
+++ linux-2.4.32/Documentation/Configure.help    2006-08-17 12:33:08.000000000 +0200
@@ -3251,6 +3251,17 @@ CONFIG_IP_NF_TARGET_LOG
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.

+CLASSIFY target support
+CONFIG_IP_NF_TARGET_CLASSIFY
+  This option adds a `CLASSIFY' target, which enables the user to set
+  the priority of a packet. Some qdiscs can use this value for classification,
+  among these are:
+
+  atm, cbq, dsmark, pfifo_fast, htb, prio
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
IP set support
CONFIG_IP_NF_SET
   This option adds IP set support to the kernel.
diff -uprN linux-2.4.32.reference/include/linux/netfilter_ipv4/ipt_CLASSIFY.h linux-2.4.32/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
--- linux-2.4.32.reference/include/linux/netfilter_ipv4/ipt_CLASSIFY.h    1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.32/include/linux/netfilter_ipv4/ipt_CLASSIFY.h    2006-08-17 12:33:08.000000000 +0200
@@ -0,0 +1,8 @@
+#ifndef _IPT_CLASSIFY_H
+#define _IPT_CLASSIFY_H
+
+struct ipt_classify_target_info {
+    u_int32_t priority;
+};
+
+#endif /*_IPT_CLASSIFY_H */
diff -uprN linux-2.4.32.reference/net/ipv4/netfilter/Config.in linux-2.4.32/net/ipv4/netfilter/Config.in
--- linux-2.4.32.reference/net/ipv4/netfilter/Config.in    2006-08-17 12:28:16.000000000 +0200
+++ linux-2.4.32/net/ipv4/netfilter/Config.in    2006-08-17 12:33:08.000000000 +0200
@@ -172,6 +172,7 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ];
     dep_tristate '    DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
 
     dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+    dep_tristate '    CLASSIFY target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_CLASSIFY $CONFIG_IP_NF_MANGLE
     dep_tristate '    IMQ target support' CONFIG_IP_NF_TARGET_IMQ $CONFIG_IP_NF_MANGLE
   fi
   if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
diff -uprN linux-2.4.32.reference/net/ipv4/netfilter/ipt_CLASSIFY.c linux-2.4.32/net/ipv4/netfilter/ipt_CLASSIFY.c
--- linux-2.4.32.reference/net/ipv4/netfilter/ipt_CLASSIFY.c    1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.32/net/ipv4/netfilter/ipt_CLASSIFY.c    2006-08-17 12:33:08.000000000 +0200
@@ -0,0 +1,82 @@
+/*
+ * This is a module which is used for setting the skb->priority field
+ * of an skb for qdisc classification.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_CLASSIFY.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("iptables qdisc classification target module");
+
+static unsigned int
+target(struct sk_buff **pskb,
+       unsigned int hooknum,
+       const struct net_device *in,
+       const struct net_device *out,
+       const void *targinfo,
+       void *userinfo)
+{
+    const struct ipt_classify_target_info *clinfo = targinfo;
+
+    if((*pskb)->priority != clinfo->priority) {
+        (*pskb)->priority = clinfo->priority;
+        (*pskb)->nfcache |= NFC_ALTERED;
+    }
+
+    return IPT_CONTINUE;
+}
+
+static int
+checkentry(const char *tablename,
+           const struct ipt_entry *e,
+           void *targinfo,
+           unsigned int targinfosize,
+           unsigned int hook_mask)
+{
+    if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){
+        printk(KERN_ERR "CLASSIFY: invalid size (%u != %u).\n",
+               targinfosize,
+               IPT_ALIGN(sizeof(struct ipt_classify_target_info)));
+        return 0;
+    }
+   
+    if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
+        printk(KERN_ERR "CLASSIFY: only valid in POST_ROUTING.\n");
+        return 0;
+    }
+
+    if (strcmp(tablename, "mangle") != 0) {
+        printk(KERN_WARNING "CLASSIFY: can only be called from "
+                            "\"mangle\" table, not \"%s\".\n",
+                            tablename);
+        return 0;
+    }
+
+    return 1;
+}
+
+static struct ipt_target ipt_classify_reg
+= { { NULL, NULL }, "CLASSIFY", target, checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+    if (ipt_register_target(&ipt_classify_reg))
+        return -EINVAL;
+
+    return 0;
+}
+
+static void __exit fini(void)
+{
+    ipt_unregister_target(&ipt_classify_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff -uprN linux-2.4.32.reference/net/ipv4/netfilter/Makefile linux-2.4.32/net/ipv4/netfilter/Makefile
--- linux-2.4.32.reference/net/ipv4/netfilter/Makefile    2006-08-17 12:28:16.000000000 +0200
+++ linux-2.4.32/net/ipv4/netfilter/Makefile    2006-08-17 12:33:08.000000000 +0200
@@ -134,6 +134,7 @@ obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_

# targets
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
+obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
obj-$(CONFIG_IP_NF_TARGET_MIRROR) += ipt_MIRROR.o
obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
--------------- snip --------------