diff options
author | /C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu </C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu> | 2008-07-02 12:20:18 +0000 |
---|---|---|
committer | /C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu </C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu> | 2008-07-02 12:20:18 +0000 |
commit | 633b62df0104203591d5c427f6769857571b2540 (patch) | |
tree | c30e45a92d662906a92822e63b256010fec005ef /kernel/ipt_set.c | |
parent | cbbb94616299ae2d897cf8a8fd8d9ebf7af41be8 (diff) |
Initial ipset release with kernel modules included.
Diffstat (limited to 'kernel/ipt_set.c')
-rw-r--r-- | kernel/ipt_set.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/kernel/ipt_set.c b/kernel/ipt_set.c new file mode 100644 index 0000000..eb064fe --- /dev/null +++ b/kernel/ipt_set.c @@ -0,0 +1,159 @@ +/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> + * Patrick Schaaf <bof@bof.de> + * Martin Josefsson <gandalf@wlug.westbo.se> + * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* Kernel module to match an IP set. */ + +#include <linux/module.h> +#include <linux/ip.h> +#include <linux/skbuff.h> +#include <linux/version.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ip_set.h> +#include <linux/netfilter_ipv4/ipt_set.h> + +static inline int +match_set(const struct ipt_set_info *info, + const struct sk_buff *skb, + int inv) +{ + if (ip_set_testip_kernel(info->index, skb, info->flags)) + inv = !inv; + return inv; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) +static bool +#else +static int +#endif +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_match *match, +#endif + const void *matchinfo, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + int offset, unsigned int protoff, bool *hotdrop) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) + int offset, unsigned int protoff, int *hotdrop) +#else + int offset, int *hotdrop) +#endif +{ + const struct ipt_set_info_match *info = matchinfo; + + return match_set(&info->match_set, + skb, + info->match_set.flags[0] & IPSET_MATCH_INV); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) +static bool +#else +static int +#endif +checkentry(const char *tablename, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) + const void *inf, +#else + const struct ipt_ip *ip, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_match *match, +#endif + void *matchinfo, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + unsigned int matchsize, +#endif + unsigned int hook_mask) +{ + struct ipt_set_info_match *info = matchinfo; + ip_set_id_t index; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) { + ip_set_printk("invalid matchsize %d", matchsize); + return 0; + } +#endif + + index = ip_set_get_byindex(info->match_set.index); + + if (index == IP_SET_INVALID_ID) { + ip_set_printk("Cannot find set indentified by id %u to match", + info->match_set.index); + return 0; /* error */ + } + if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) { + ip_set_printk("That's nasty!"); + return 0; /* error */ + } + + return 1; +} + +static void destroy( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_match *match, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + void *matchinfo, unsigned int matchsize) +#else + void *matchinfo) +#endif +{ + struct ipt_set_info_match *info = matchinfo; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) { + ip_set_printk("invalid matchsize %d", matchsize); + return; + } +#endif + ip_set_put(info->match_set.index); +} + +static struct ipt_match set_match = { + .name = "set", +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + .family = AF_INET, +#endif + .match = &match, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + .matchsize = sizeof(struct ipt_set_info_match), +#endif + .checkentry = &checkentry, + .destroy = &destroy, + .me = THIS_MODULE +}; + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); +MODULE_DESCRIPTION("iptables IP set match module"); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) +#define ipt_register_match xt_register_match +#define ipt_unregister_match xt_unregister_match +#endif + +static int __init ipt_ipset_init(void) +{ + return ipt_register_match(&set_match); +} + +static void __exit ipt_ipset_fini(void) +{ + ipt_unregister_match(&set_match); +} + +module_init(ipt_ipset_init); +module_exit(ipt_ipset_fini); |