mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-06 04:35:12 +02:00

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>
217 lines
5.6 KiB
C
217 lines
5.6 KiB
C
#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");
|