Add a compat wrapper to make modules work with older Linux.

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>
This commit is contained in:
Jan Engelhardt
2008-01-29 15:40:57 +01:00
parent 7a981b17b5
commit 47b700b0f5
8 changed files with 343 additions and 7 deletions

View File

@@ -4,7 +4,7 @@ Prerequirements
* iptables-devel 1.4.1 * iptables-devel 1.4.1
* kernel-source * kernel-source >= 2.6.19
Compiling Compiling

View File

@@ -2,3 +2,4 @@
obj-m += xt_TARPIT.o obj-m += xt_TARPIT.o
obj-m += xt_TEE.o obj-m += xt_TEE.o
obj-m += compat_xtables.o

View File

@@ -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 */

216
extensions/compat_xtables.c Normal file
View File

@@ -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");

View File

@@ -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 */

70
extensions/compat_xtnu.h Normal file
View File

@@ -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 */

View File

@@ -44,6 +44,7 @@
#endif #endif
#include <net/route.h> #include <net/route.h>
#include <net/tcp.h> #include <net/tcp.h>
#include "compat_xtables.h"
static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook) static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook)
{ {

View File

@@ -17,11 +17,6 @@
#include <net/ip.h> #include <net/ip.h>
#include <net/route.h> #include <net/route.h>
#include <linux/netfilter/x_tables.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) #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
# define WITH_CONNTRACK 1 # define WITH_CONNTRACK 1
@@ -29,6 +24,9 @@
static struct nf_conn tee_track; static struct nf_conn tee_track;
#endif #endif
#include "compat_xtables.h"
#include "xt_TEE.h"
static const union nf_inet_addr zero_address; 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); unsigned int hh_len = LL_RESERVED_SPACE(dev);
/* Be paranoid, rather than too clever. */ /* 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; struct sk_buff *skb2;
skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev)); skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));