diff --git a/INSTALL b/INSTALL index 0102b49..ed1f35c 100644 --- a/INSTALL +++ b/INSTALL @@ -4,7 +4,7 @@ Prerequirements * iptables-devel 1.4.1 - * kernel-source + * kernel-source >= 2.6.19 Compiling diff --git a/extensions/Kbuild b/extensions/Kbuild index 96aca1a..73c477f 100644 --- a/extensions/Kbuild +++ b/extensions/Kbuild @@ -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 index 0000000..8c74ae1 --- /dev/null +++ b/extensions/compat_nfinetaddr.h @@ -0,0 +1,14 @@ +#ifndef _COMPAT_NFINETADDR_H +#define _COMPAT_NFINETADDR_H 1 + +#include +#include + +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 index 0000000..e095f95 --- /dev/null +++ b/extensions/compat_xtables.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#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 index 0000000..ac3b3b5 --- /dev/null +++ b/extensions/compat_xtables.h @@ -0,0 +1,35 @@ +#ifndef _XTABLES_COMPAT_H +#define _XTABLES_COMPAT_H 1 + +#include + +#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 index 0000000..b7dabb1 --- /dev/null +++ b/extensions/compat_xtnu.h @@ -0,0 +1,70 @@ +#ifndef _COMPAT_XTNU_H +#define _COMPAT_XTNU_H 1 + +#include +#include +#include + +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 */ diff --git a/extensions/xt_TARPIT.c b/extensions/xt_TARPIT.c index 3338176..3109435 100644 --- a/extensions/xt_TARPIT.c +++ b/extensions/xt_TARPIT.c @@ -44,6 +44,7 @@ #endif #include #include +#include "compat_xtables.h" static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook) { diff --git a/extensions/xt_TEE.c b/extensions/xt_TEE.c index 265d82f..93980f2 100644 --- a/extensions/xt_TEE.c +++ b/extensions/xt_TEE.c @@ -17,11 +17,6 @@ #include #include #include -#ifdef CONFIG_NETFILTER_XT_TARGET_TEE -# include -#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));