]> git.ipfire.org Git - thirdparty/xtables-addons.git/commitdiff
Add a compat wrapper to make modules work with older Linux.
authorJan Engelhardt <jengelh@computergmbh.de>
Tue, 29 Jan 2008 14:40:57 +0000 (15:40 +0100)
committerJan Engelhardt <jengelh@computergmbh.de>
Tue, 29 Jan 2008 14:40:57 +0000 (15:40 +0100)
The extension modules use the API of a fairly recent kernel, if not
even the networking git tree. To make it work with older Linux
kernels, an API wrapper is added. Should compile against
running-kernels Linux 2.6.19..current (tested: 2.6.22..current).

Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
INSTALL
extensions/Kbuild
extensions/compat_nfinetaddr.h [new file with mode: 0644]
extensions/compat_xtables.c [new file with mode: 0644]
extensions/compat_xtables.h [new file with mode: 0644]
extensions/compat_xtnu.h [new file with mode: 0644]
extensions/xt_TARPIT.c
extensions/xt_TEE.c

diff --git a/INSTALL b/INSTALL
index 0102b493486fa317af7f1b977caf412cbd752412..ed1f35c4240c228fbddef2d2c7448db9ae0d8621 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -4,7 +4,7 @@ Prerequirements
 
        * iptables-devel 1.4.1
 
-       * kernel-source
+       * kernel-source >= 2.6.19
 
 
 Compiling
index 96aca1ace05f7f4ef95610bfe1e6d2d343b845ef..73c477f27991833d45b8ee165edb05c45ff0d87d 100644 (file)
@@ -2,3 +2,4 @@
 
 obj-m += xt_TARPIT.o
 obj-m += xt_TEE.o
+obj-m += compat_xtables.o
diff --git a/extensions/compat_nfinetaddr.h b/extensions/compat_nfinetaddr.h
new file mode 100644 (file)
index 0000000..8c74ae1
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _COMPAT_NFINETADDR_H
+#define _COMPAT_NFINETADDR_H 1
+
+#include <linux/in.h>
+#include <linux/in6.h>
+
+union nf_inet_addr {
+       __be32 ip;
+       __be32 ip6[4];
+       struct in_addr in;
+       struct in6_addr in6;
+};
+
+#endif /* _COMPAT_NFINETADDR_H */
diff --git a/extensions/compat_xtables.c b/extensions/compat_xtables.c
new file mode 100644 (file)
index 0000000..e095f95
--- /dev/null
@@ -0,0 +1,216 @@
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/version.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/x_tables.h>
+#include "compat_xtnu.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && \
+    LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
+static int xtnu_match_run(const struct sk_buff *skb,
+    const struct net_device *in, const struct net_device *out,
+    const struct xt_match *cm, const void *matchinfo, int offset,
+    unsigned int protoff, int *hotdrop)
+{
+       struct xtnu_match *nm = xtcompat_numatch(cm);
+       bool lo_drop, lo_ret;
+
+       if (nm == NULL || nm->match == NULL)
+               return false;
+       lo_ret = nm->match(skb, in, out, nm, matchinfo,
+                offset, protoff, &lo_drop);
+       *hotdrop = lo_drop;
+       return lo_ret;
+}
+
+static int xtnu_match_check(const char *table, const void *entry,
+    const struct xt_match *cm, void *matchinfo, unsigned int hook_mask)
+{
+       struct xtnu_match *nm = xtcompat_numatch(cm);
+
+       if (nm == NULL)
+               return false;
+       if (nm->checkentry == NULL)
+               return true;
+       return nm->checkentry(table, entry, nm, matchinfo, hook_mask);
+}
+
+static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo)
+{
+       struct xtnu_match *nm = xtcompat_numatch(cm);
+
+       if (nm != NULL && nm->destroy != NULL)
+               nm->destroy(nm, matchinfo);
+}
+
+int xtnu_register_match(struct xtnu_match *nt)
+{
+       struct xt_match *ct;
+       char *tmp;
+       int ret;
+
+       ct = kzalloc(sizeof(struct xt_match), GFP_KERNEL);
+       if (ct == NULL)
+               return -ENOMEM;
+
+       tmp = (char *)ct->name;
+       memcpy(tmp, nt->name, sizeof(nt->name));
+       tmp = (char *)(ct->name + sizeof(ct->name) - sizeof(void *));
+       *(tmp-1) = '\0';
+       memcpy(tmp, &nt, sizeof(void *));
+
+       ct->revision   = nt->revision;
+       ct->family     = nt->family;
+       ct->table      = (char *)nt->table;
+       ct->hooks      = nt->hooks;
+       ct->proto      = nt->proto;
+       ct->match      = xtnu_match_run;
+       ct->checkentry = xtnu_match_check;
+       ct->destroy    = xtnu_match_destroy;
+       ct->matchsize  = nt->matchsize;
+       ct->me         = nt->me;
+
+       nt->__compat_match = ct;
+       ret = xt_register_match(ct);
+       if (ret != 0)
+               kfree(ct);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(xtnu_register_match);
+
+int xtnu_register_matches(struct xtnu_match *nt, unsigned int num)
+{
+       unsigned int i;
+       int ret;
+
+       for (i = 0; i < num; ++i) {
+               ret = xtnu_register_match(&nt[i]);
+               if (ret < 0) {
+                       if (i > 0)
+                               xtnu_unregister_matches(nt, i);
+                       return ret;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xtnu_register_matches);
+
+void xtnu_unregister_match(struct xtnu_match *nt)
+{
+       xt_unregister_match(nt->__compat_match);
+       kfree(nt->__compat_match);
+}
+EXPORT_SYMBOL_GPL(xtnu_unregister_match);
+
+void xtnu_unregister_matches(struct xtnu_match *nt, unsigned int num)
+{
+       unsigned int i;
+
+       for (i = 0; i < num; ++i)
+               xtnu_unregister_match(&nt[i]);
+}
+EXPORT_SYMBOL_GPL(xtnu_unregister_matches);
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
+static int xtnu_target_check(const char *table, const void *entry,
+    const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
+{
+       struct xtnu_target *nt = xtcompat_nutarget(ct);
+       if (nt == NULL)
+               return false;
+       if (nt->checkentry == NULL)
+               /* this is valid, just like if there was no function */
+               return true;
+       return nt->checkentry(table, entry, nt, targinfo, hook_mask);
+}
+#endif
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 23)
+static bool xtnu_target_check(const char *table, const void *entry,
+    const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
+{
+       struct xtnu_target *nt = xtcompat_nutarget(ct);
+       if (nt == NULL)
+               return false;
+       if (nt->checkentry == NULL)
+               /* this is valid, just like if there was no function */
+               return true;
+       return nt->checkentry(table, entry, nt, targinfo, hook_mask);
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && \
+    LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
+static unsigned int xtnu_target_run(struct sk_buff **pskb,
+    const struct net_device *in, const struct net_device *out,
+    unsigned int hooknum, const struct xt_target *ct, const void *targinfo)
+{
+       struct xtnu_target *nt = xtcompat_nutarget(ct);
+       if (nt != NULL && nt->target != NULL)
+               return nt->target(*pskb, in, out, hooknum, nt, targinfo);
+       return XT_CONTINUE;
+}
+
+static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo)
+{
+       struct xtnu_target *nt = xtcompat_nutarget(ct);
+       if (nt != NULL && nt->destroy != NULL)
+               nt->destroy(nt, targinfo);
+}
+
+int xtnu_register_target(struct xtnu_target *nt)
+{
+       struct xt_target *ct;
+       char *tmp;
+       int ret;
+
+       ct = kzalloc(sizeof(struct xt_target), GFP_KERNEL);
+       if (ct == NULL)
+               return -ENOMEM;
+
+       tmp = (char *)ct->name;
+       memcpy(tmp, nt->name, sizeof(nt->name));
+       tmp = (char *)(ct->name + sizeof(ct->name) - sizeof(void *));
+       *(tmp-1) = '\0';
+       memcpy(tmp, &nt, sizeof(void *));
+
+       ct->revision   = nt->revision;
+       ct->family     = nt->family;
+       ct->table      = (char *)nt->table;
+       ct->hooks      = nt->hooks;
+       ct->proto      = nt->proto;
+       ct->target     = xtnu_target_run;
+       ct->checkentry = xtnu_target_check;
+       ct->destroy    = xtnu_target_destroy;
+       ct->targetsize = nt->targetsize;
+       ct->me         = nt->me;
+
+       nt->__compat_target = ct;
+       ret = xt_register_target(ct);
+       if (ret != 0)
+               kfree(ct);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(xtnu_register_target);
+
+void xtnu_unregister_target(struct xtnu_target *nt)
+{
+       xt_unregister_target(nt->__compat_target);
+       kfree(nt->__compat_target);
+}
+EXPORT_SYMBOL_GPL(xtnu_unregister_target);
+
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
+int xtnu_ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type)
+{
+       return ip_route_me_harder(&skb, addr_type);
+}
+EXPORT_SYMBOL_GPL(xtnu_ip_route_me_harder);
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/extensions/compat_xtables.h b/extensions/compat_xtables.h
new file mode 100644 (file)
index 0000000..ac3b3b5
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _XTABLES_COMPAT_H
+#define _XTABLES_COMPAT_H 1
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+#      define NF_INET_PRE_ROUTING  NF_IP_PRE_ROUTING
+#      define NF_INET_LOCAL_IN     NF_IP_LOCAL_IN
+#      define NF_INET_FORWARD      NF_IP_FORWARD
+#      define NF_INET_LOCAL_OUT    NF_IP_LOCAL_OUT
+#      define NF_INET_POST_ROUTING NF_IP_POST_ROUTING
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
+#      include "compat_nfinetaddr.h"
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
+#      define xt_match              xtnu_match
+#      define xt_register_match     xtnu_register_match
+#      define xt_unregister_match   xtnu_unregister_match
+#      define xt_register_matches   xtnu_register_matches
+#      define xt_unregister_matches xtnu_unregister_matches
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
+#      define xt_target             xtnu_target
+#      define ip_route_me_harder    xtnu_ip_route_me_harder
+#      define xt_register_target    xtnu_register_target
+#      define xt_unregister_target  xtnu_unregister_target
+#endif
+
+#include "compat_xtnu.h"
+
+#endif /* _XTABLES_COMPAT_H */
diff --git a/extensions/compat_xtnu.h b/extensions/compat_xtnu.h
new file mode 100644 (file)
index 0000000..b7dabb1
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _COMPAT_XTNU_H
+#define _COMPAT_XTNU_H 1
+
+#include <linux/list.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/spinlock.h>
+
+struct module;
+struct net_device;
+struct sk_buff;
+
+struct xtnu_match {
+       struct list_head list;
+       char name[XT_FUNCTION_MAXNAMELEN - 1 - sizeof(void *)];
+       bool (*match)(const struct sk_buff *, const struct net_device *,
+               const struct net_device *, const struct xtnu_match *,
+               const void *, int, unsigned int, bool *);
+       bool (*checkentry)(const char *, const void *,
+               const struct xtnu_match *, void *, unsigned int);
+       void (*destroy)(const struct xtnu_match *, void *);
+       struct module *me;
+       const char *table;
+       unsigned int matchsize, hooks;
+       unsigned short proto, family;
+       uint8_t revision;
+
+       void *__compat_match;
+};
+
+struct xtnu_target {
+       struct list_head list;
+       char name[XT_FUNCTION_MAXNAMELEN - 1 - sizeof(void *)];
+       unsigned int (*target)(struct sk_buff *, const struct net_device *,
+               const struct net_device *, unsigned int,
+               const struct xtnu_target *, const void *);
+       bool (*checkentry)(const char *, const void *,
+               const struct xtnu_target *, void *, unsigned int);
+       void (*destroy)(const struct xtnu_target *, void *);
+       struct module *me;
+       const char *table;
+       unsigned int targetsize, hooks;
+       unsigned short proto, family;
+       uint8_t revision;
+
+       void *__compat_target;
+};
+
+static inline struct xtnu_match *xtcompat_numatch(const struct xt_match *m)
+{
+       void *q;
+       memcpy(&q, m->name + sizeof(m->name) - sizeof(void *), sizeof(void *));
+       return q;
+}
+
+static inline struct xtnu_target *xtcompat_nutarget(const struct xt_target *t)
+{
+       void *q;
+       memcpy(&q, t->name + sizeof(t->name) - sizeof(void *), sizeof(void *));
+       return q;
+}
+
+extern int xtnu_ip_route_me_harder(struct sk_buff *, unsigned int);
+extern int xtnu_register_match(struct xtnu_match *);
+extern void xtnu_unregister_match(struct xtnu_match *);
+extern int xtnu_register_matches(struct xtnu_match *, unsigned int);
+extern void xtnu_unregister_matches(struct xtnu_match *, unsigned int);
+extern int xtnu_register_target(struct xtnu_target *);
+extern void xtnu_unregister_target(struct xtnu_target *);
+
+#endif /* _COMPAT_XTNU_H */
index 3338176cecef45bb922fa365d66e05cd336c38a3..3109435ae345ce7871a9967bd506b4f92e498dd0 100644 (file)
@@ -44,6 +44,7 @@
 #endif
 #include <net/route.h>
 #include <net/tcp.h>
+#include "compat_xtables.h"
 
 static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook)
 {
index 265d82fb67c6fddd312c67cc1fdae25a041a811e..93980f2467af74fa22acb94d493405dd47664015 100644 (file)
 #include <net/ip.h>
 #include <net/route.h>
 #include <linux/netfilter/x_tables.h>
-#ifdef CONFIG_NETFILTER_XT_TARGET_TEE
-#      include <linux/netfilter/xt_TEE.h>
-#else
-#      include "xt_TEE.h"
-#endif
 
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 #      define WITH_CONNTRACK 1
@@ -29,6 +24,9 @@
 static struct nf_conn tee_track;
 #endif
 
+#include "compat_xtables.h"
+#include "xt_TEE.h"
+
 static const union nf_inet_addr zero_address;
 
 /*
@@ -101,7 +99,8 @@ static void tee_ip_direct_send(struct sk_buff *skb)
        unsigned int hh_len = LL_RESERVED_SPACE(dev);
 
        /* Be paranoid, rather than too clever. */
-       if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops != NULL)) {
+       if (unlikely(skb_headroom(skb) < hh_len)) {
+       /* if (dev->header_ops != NULL) */
                struct sk_buff *skb2;
 
                skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));