mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-06 04:35:12 +02:00
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:
2
INSTALL
2
INSTALL
@@ -4,7 +4,7 @@ Prerequirements
|
|||||||
|
|
||||||
* iptables-devel 1.4.1
|
* iptables-devel 1.4.1
|
||||||
|
|
||||||
* kernel-source
|
* kernel-source >= 2.6.19
|
||||||
|
|
||||||
|
|
||||||
Compiling
|
Compiling
|
||||||
|
@@ -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
|
||||||
|
14
extensions/compat_nfinetaddr.h
Normal file
14
extensions/compat_nfinetaddr.h
Normal 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
216
extensions/compat_xtables.c
Normal 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");
|
35
extensions/compat_xtables.h
Normal file
35
extensions/compat_xtables.h
Normal 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
70
extensions/compat_xtnu.h
Normal 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 */
|
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -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));
|
||||||
|
Reference in New Issue
Block a user