mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-20 19:44:56 +02:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5b1bfedb82 | ||
![]() |
ee7e4f5a42 | ||
![]() |
d20d1922db | ||
![]() |
be6fbee56a | ||
![]() |
3c0b26c4b9 | ||
![]() |
25e2fbdf7d | ||
![]() |
5bd67db123 | ||
![]() |
f3737502bd | ||
![]() |
74e7eb283a | ||
![]() |
f3f0741469 | ||
![]() |
9c43965a86 | ||
![]() |
3a4e719b8c |
8
INSTALL
8
INSTALL
@@ -12,13 +12,9 @@ in combination with the kernel's Kbuild system.
|
||||
Prerequirements
|
||||
===============
|
||||
|
||||
* a recent iptables snapshot
|
||||
- from the "xtables" git repository at dev.medozas.de
|
||||
(minimum as per git-describe: v1.4.0-77)
|
||||
- or the subversion repository at netfilter.org (minimum: r7502)
|
||||
- or the xtables-combined tarball that is currently distributed
|
||||
* iptables 1.4.1
|
||||
|
||||
* kernel-source >= 2.6.18.5 with prepared build/output directory
|
||||
* kernel-source >= 2.6.17 with prepared build/output directory
|
||||
- CONFIG_NF_CONNTRACK or CONFIG_IP_NF_CONNTRACK
|
||||
- CONFIG_NF_CONNTRACK_MARK or CONFIG_IP_NF_CONNTRACK_MARK
|
||||
enabled =y or as module (=m)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
|
||||
AC_INIT([xtables-addons], [1.5.7])
|
||||
AC_INIT([xtables-addons], [1.6])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_PROG_INSTALL
|
||||
AM_INIT_AUTOMAKE
|
||||
|
1
extensions/.gitignore
vendored
1
extensions/.gitignore
vendored
@@ -4,6 +4,7 @@
|
||||
*.ko
|
||||
*.mod.c
|
||||
Module.symvers
|
||||
Modules.symvers
|
||||
modules.order
|
||||
|
||||
/*.so
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
top_srcdir := @top_srcdir@
|
||||
srcdir := @srcdir@
|
||||
abstop_srcdir := $(shell readlink -e ${top_srcdir})
|
||||
abssrcdir := $(shell readlink -e ${srcdir})
|
||||
abstop_srcdir := $(shell readlink -f ${top_srcdir})
|
||||
abssrcdir := $(shell readlink -f ${srcdir})
|
||||
|
||||
ifeq (${abstop_srcdir},)
|
||||
$(error Path resolution of ${top_srcdir} failed)
|
||||
|
@@ -20,19 +20,40 @@
|
||||
#include "compat_skbuff.h"
|
||||
#include "compat_xtnu.h"
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
typedef __u16 __bitwise __sum16;
|
||||
typedef __u32 __bitwise __wsum;
|
||||
#endif
|
||||
|
||||
#if 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)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static bool 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, bool *hotdrop)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
bool lo_drop = false, lo_ret;
|
||||
struct xt_match_param local_par = {
|
||||
.in = in,
|
||||
.out = out,
|
||||
.match = cm,
|
||||
.matchinfo = matchinfo,
|
||||
.fragoff = offset,
|
||||
.thoff = protoff,
|
||||
.hotdrop = &lo_drop,
|
||||
.family = NFPROTO_UNSPEC, /* don't have that info */
|
||||
};
|
||||
|
||||
if (nm == NULL || nm->match == NULL)
|
||||
return false;
|
||||
lo_ret = nm->match(skb, in, out, nm, matchinfo,
|
||||
offset, protoff, &lo_drop);
|
||||
lo_ret = nm->match(skb, &local_par);
|
||||
*hotdrop = lo_drop;
|
||||
return lo_ret;
|
||||
}
|
||||
@@ -45,35 +66,51 @@ static int xtnu_match_check(const char *table, const void *entry,
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
static int xtnu_match_check(const char *table, const void *entry,
|
||||
const struct xt_match *cm, void *matchinfo, unsigned int hook_mask)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static bool xtnu_match_check(const char *table, const void *entry,
|
||||
const struct xt_match *cm, void *matchinfo, unsigned int hook_mask)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
struct xt_mtchk_param local_par = {
|
||||
.table = table,
|
||||
.entryinfo = entry,
|
||||
.match = cm,
|
||||
.matchinfo = matchinfo,
|
||||
.hook_mask = hook_mask,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nm == NULL)
|
||||
return false;
|
||||
if (nm->checkentry == NULL)
|
||||
return true;
|
||||
return nm->checkentry(table, entry, nm, matchinfo, hook_mask);
|
||||
return nm->checkentry(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo,
|
||||
unsigned int matchinfosize)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
struct xt_mtdtor_param local_par = {
|
||||
.match = cm,
|
||||
.matchinfo = matchinfo,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nm != NULL && nm->destroy != NULL)
|
||||
nm->destroy(nm, matchinfo);
|
||||
nm->destroy(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
int xtnu_register_match(struct xtnu_match *nt)
|
||||
{
|
||||
struct xt_match *ct;
|
||||
@@ -152,18 +189,36 @@ static unsigned int xtnu_target_run(struct sk_buff **pskb,
|
||||
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)
|
||||
#else
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static unsigned int xtnu_target_run(struct sk_buff *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *ct, const void *targinfo)
|
||||
#else
|
||||
static unsigned int
|
||||
xtnu_target_run(struct sk_buff *skb, const struct xt_target_param *par)
|
||||
#endif
|
||||
{
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
struct xt_target_param local_par = {
|
||||
.in = in,
|
||||
.out = out,
|
||||
.hooknum = hooknum,
|
||||
.target = ct,
|
||||
.targinfo = targinfo,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
#else
|
||||
struct xtnu_target *nt = xtcompat_nutarget(par->target);
|
||||
#endif
|
||||
|
||||
if (nt != NULL && nt->target != NULL)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return nt->target(pskb, in, out, hooknum, nt, targinfo);
|
||||
return nt->target(pskb, &local_par);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
return nt->target(&skb, &local_par);
|
||||
#else
|
||||
return nt->target(&skb, in, out, hooknum, nt, targinfo);
|
||||
return nt->target(&skb, par);
|
||||
#endif
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
@@ -175,31 +230,50 @@ static int xtnu_target_check(const char *table, const void *entry,
|
||||
#elif 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)
|
||||
#else
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static bool xtnu_target_check(const char *table, const void *entry,
|
||||
const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
struct xt_tgchk_param local_par = {
|
||||
.table = table,
|
||||
.entryinfo = entry,
|
||||
.target = ct,
|
||||
.targinfo = targinfo,
|
||||
.hook_mask = hook_mask,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
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);
|
||||
return nt->checkentry(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo,
|
||||
unsigned int targinfosize)
|
||||
#else
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
struct xt_tgdtor_param local_par = {
|
||||
.target = ct,
|
||||
.targinfo = targinfo,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nt != NULL && nt->destroy != NULL)
|
||||
nt->destroy(nt, targinfo);
|
||||
nt->destroy(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
int xtnu_register_target(struct xtnu_target *nt)
|
||||
{
|
||||
@@ -223,8 +297,13 @@ int xtnu_register_target(struct xtnu_target *nt)
|
||||
ct->hooks = nt->hooks;
|
||||
ct->proto = nt->proto;
|
||||
ct->target = xtnu_target_run;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
ct->checkentry = xtnu_target_check;
|
||||
ct->destroy = xtnu_target_destroy;
|
||||
#else
|
||||
ct->checkentry = nt->checkentry;
|
||||
ct->destroy = nt->destroy;
|
||||
#endif
|
||||
ct->targetsize = nt->targetsize;
|
||||
ct->me = nt->me;
|
||||
|
||||
@@ -384,18 +463,31 @@ int xtnu_neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_neigh_hh_output);
|
||||
|
||||
static inline void csum_replace4(__sum16 *sum, __be32 from, __be32 to)
|
||||
static inline __wsum xtnu_csum_unfold(__sum16 n)
|
||||
{
|
||||
return (__force __wsum)n;
|
||||
}
|
||||
|
||||
static inline void xtnu_csum_replace4(__sum16 *sum, __be32 from, __be32 to)
|
||||
{
|
||||
__be32 diff[] = {~from, to};
|
||||
*sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
|
||||
~csum_unfold(*sum)));
|
||||
~xtnu_csum_unfold(*sum)));
|
||||
}
|
||||
|
||||
void xtnu_csum_replace2(__sum16 *sum, __be16 from, __be16 to)
|
||||
{
|
||||
csum_replace4(sum, (__force __be32)from, (__force __be32)to);
|
||||
xtnu_csum_replace4(sum, (__force __be32)from, (__force __be32)to);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_csum_replace2);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
|
||||
int xtnu_skb_linearize(struct sk_buff *skb)
|
||||
{
|
||||
return skb_linearize(skb, GFP_ATOMIC);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_skb_linearize);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -5,8 +5,8 @@
|
||||
#include "compat_skbuff.h"
|
||||
#include "compat_xtnu.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
# warning Kernels below 2.6.18.5 not supported.
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
|
||||
# warning Kernels below 2.6.17 not supported.
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
@@ -26,6 +26,11 @@
|
||||
# warning You need either CONFIG_NF_CONNTRACK or CONFIG_IP_NF_CONNTRACK.
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
|
||||
# define skb_init_secmark(skb)
|
||||
# define skb_linearize xtnu_skb_linearize
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
# define neigh_hh_output xtnu_neigh_hh_output
|
||||
# define IPPROTO_UDPLITE 136
|
||||
@@ -51,7 +56,7 @@
|
||||
# define init_net__proc_net init_net.proc_net
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
# define xt_match xtnu_match
|
||||
# define xt_register_match xtnu_register_match
|
||||
# define xt_unregister_match xtnu_unregister_match
|
||||
|
@@ -17,15 +17,72 @@ struct net_device;
|
||||
struct rtable;
|
||||
struct sk_buff;
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
enum {
|
||||
NFPROTO_UNSPEC = 0,
|
||||
NFPROTO_IPV4 = 2,
|
||||
NFPROTO_ARP = 3,
|
||||
NFPROTO_BRIDGE = 7,
|
||||
NFPROTO_IPV6 = 10,
|
||||
NFPROTO_DECNET = 12,
|
||||
NFPROTO_NUMPROTO,
|
||||
};
|
||||
|
||||
struct xt_match_param {
|
||||
const struct net_device *in, *out;
|
||||
const struct xt_match *match;
|
||||
const void *matchinfo;
|
||||
int fragoff;
|
||||
unsigned int thoff;
|
||||
bool *hotdrop;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_mtchk_param {
|
||||
const char *table;
|
||||
const void *entryinfo;
|
||||
const struct xt_match *match;
|
||||
void *matchinfo;
|
||||
unsigned int hook_mask;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_mtdtor_param {
|
||||
const struct xt_match *match;
|
||||
void *matchinfo;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_target_param {
|
||||
const struct net_device *in, *out;
|
||||
unsigned int hooknum;
|
||||
const struct xt_target *target;
|
||||
const void *targinfo;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_tgchk_param {
|
||||
const char *table;
|
||||
const void *entryinfo;
|
||||
const struct xt_target *target;
|
||||
void *targinfo;
|
||||
unsigned int hook_mask;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_tgdtor_param {
|
||||
const struct xt_target *target;
|
||||
void *targinfo;
|
||||
u_int8_t family;
|
||||
};
|
||||
#endif
|
||||
|
||||
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 *);
|
||||
bool (*match)(const struct sk_buff *, const struct xt_match_param *);
|
||||
bool (*checkentry)(const struct xt_mtchk_param *);
|
||||
void (*destroy)(const struct xt_mtdtor_param *);
|
||||
struct module *me;
|
||||
const char *table;
|
||||
unsigned int matchsize, hooks;
|
||||
@@ -38,12 +95,10 @@ struct xtnu_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 *);
|
||||
unsigned int (*target)(struct sk_buff **,
|
||||
const struct xt_target_param *);
|
||||
bool (*checkentry)(const struct xt_tgchk_param *);
|
||||
void (*destroy)(const struct xt_tgdtor_param *);
|
||||
struct module *me;
|
||||
const char *table;
|
||||
unsigned int targetsize, hooks;
|
||||
@@ -82,5 +137,7 @@ extern void xtnu_unregister_targets(struct xtnu_target *, unsigned int);
|
||||
extern struct xt_match *xtnu_request_find_match(unsigned int,
|
||||
const char *, uint8_t);
|
||||
extern int xtnu_neigh_hh_output(struct hh_cache *, struct sk_buff *);
|
||||
extern void xtnu_csum_replace2(__u16 __bitwise *, __be16, __be16);
|
||||
extern int xtnu_skb_linearize(struct sk_buff *);
|
||||
|
||||
#endif /* _COMPAT_XTNU_H */
|
||||
|
@@ -29,7 +29,7 @@ regular_CFLAGS := @regular_CFLAGS@
|
||||
kinclude_CFLAGS := @kinclude_CFLAGS@
|
||||
xtables_CFLAGS := @xtables_CFLAGS@
|
||||
|
||||
AM_CFLAGS := ${regular_CFLAGS} -I${top_srcdir}/include ${xtables_CFLAGS} ${kinclude_CFLAGS} -DXTABLES_LIBDIR=\"${xtlibdir}\"
|
||||
AM_CFLAGS := ${regular_CFLAGS} -I${top_srcdir}/include ${xtables_CFLAGS} ${kinclude_CFLAGS} -DIPSET_LIB_DIR=\"${xtlibdir}\"
|
||||
AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
|
||||
|
||||
ifeq (${V},)
|
||||
|
@@ -20,20 +20,20 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/capability.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
|
||||
# include <linux/semaphore.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
|
||||
#include <asm/semaphore.h>
|
||||
#else
|
||||
# include <asm/semaphore.h>
|
||||
#include <linux/semaphore.h>
|
||||
#endif
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#define ASSERT_READ_LOCK(x)
|
||||
#define ASSERT_WRITE_LOCK(x)
|
||||
#include <linux/netfilter.h>
|
||||
#include "ip_set.h"
|
||||
|
||||
static struct list_head set_type_list; /* all registered sets */
|
||||
@@ -137,7 +137,7 @@ ip_set_hash_del(ip_set_id_t id, ip_set_ip_t ip)
|
||||
|
||||
if (set_hash != NULL)
|
||||
__set_hash_del(set_hash);
|
||||
write_unlock_bh(&ip_set_lock);
|
||||
write_unlock_bh(&ip_set_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -235,10 +235,10 @@ ip_set_testip_kernel(ip_set_id_t index,
|
||||
&& follow_bindings(index, set, ip));
|
||||
read_unlock_bh(&ip_set_lock);
|
||||
|
||||
return res;
|
||||
return (res < 0 ? 0 : res);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
ip_set_addip_kernel(ip_set_id_t index,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags)
|
||||
@@ -268,9 +268,11 @@ ip_set_addip_kernel(ip_set_id_t index,
|
||||
&& set->type->retry
|
||||
&& (res = set->type->retry(set)) == 0)
|
||||
goto retry;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
ip_set_delip_kernel(ip_set_id_t index,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags)
|
||||
@@ -294,6 +296,8 @@ ip_set_delip_kernel(ip_set_id_t index,
|
||||
&& flags[i]
|
||||
&& follow_bindings(index, set, ip));
|
||||
read_unlock_bh(&ip_set_lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Register and deregister settype */
|
||||
@@ -358,6 +362,29 @@ ip_set_unregister_set_type(struct ip_set_type *set_type)
|
||||
|
||||
}
|
||||
|
||||
ip_set_id_t
|
||||
__ip_set_get_byname(const char *name, struct ip_set **set)
|
||||
{
|
||||
ip_set_id_t i, index = IP_SET_INVALID_ID;
|
||||
|
||||
for (i = 0; i < ip_set_max; i++) {
|
||||
if (ip_set_list[i] != NULL
|
||||
&& SETNAME_EQ(ip_set_list[i]->name, name)) {
|
||||
__ip_set_get(i);
|
||||
index = i;
|
||||
*set = ip_set_list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void __ip_set_put_byindex(ip_set_id_t index)
|
||||
{
|
||||
if (ip_set_list[index])
|
||||
__ip_set_put(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Userspace routines
|
||||
*/
|
||||
@@ -407,12 +434,26 @@ ip_set_get_byindex(ip_set_id_t index)
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the set id belonging to the index.
|
||||
* We are protected by the mutex, so we do not need to use
|
||||
* ip_set_lock. There is no need to reference the sets either.
|
||||
*/
|
||||
ip_set_id_t
|
||||
ip_set_id(ip_set_id_t index)
|
||||
{
|
||||
if (index >= ip_set_max || !ip_set_list[index])
|
||||
return IP_SET_INVALID_ID;
|
||||
|
||||
return ip_set_list[index]->id;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the given set pointer points to a valid set, decrement
|
||||
* reference count by 1. The caller shall not assume the index
|
||||
* to be valid, after calling this function.
|
||||
*/
|
||||
void ip_set_put(ip_set_id_t index)
|
||||
void ip_set_put_byindex(ip_set_id_t index)
|
||||
{
|
||||
down(&ip_set_app_mutex);
|
||||
if (ip_set_list[index])
|
||||
@@ -490,7 +531,16 @@ ip_set_addip(ip_set_id_t index,
|
||||
const void *data,
|
||||
size_t size)
|
||||
{
|
||||
struct ip_set *set = ip_set_list[index];
|
||||
|
||||
IP_SET_ASSERT(set);
|
||||
|
||||
if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
set->type->reqsize,
|
||||
size - sizeof(struct ip_set_req_adt));
|
||||
return -EINVAL;
|
||||
}
|
||||
return __ip_set_addip(index,
|
||||
data + sizeof(struct ip_set_req_adt),
|
||||
size - sizeof(struct ip_set_req_adt));
|
||||
@@ -506,6 +556,13 @@ ip_set_delip(ip_set_id_t index,
|
||||
int res;
|
||||
|
||||
IP_SET_ASSERT(set);
|
||||
|
||||
if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
set->type->reqsize,
|
||||
size - sizeof(struct ip_set_req_adt));
|
||||
return -EINVAL;
|
||||
}
|
||||
write_lock_bh(&set->lock);
|
||||
res = set->type->delip(set,
|
||||
data + sizeof(struct ip_set_req_adt),
|
||||
@@ -526,6 +583,13 @@ ip_set_testip(ip_set_id_t index,
|
||||
int res;
|
||||
|
||||
IP_SET_ASSERT(set);
|
||||
|
||||
if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
set->type->reqsize,
|
||||
size - sizeof(struct ip_set_req_adt));
|
||||
return -EINVAL;
|
||||
}
|
||||
res = __ip_set_testip(set,
|
||||
data + sizeof(struct ip_set_req_adt),
|
||||
size - sizeof(struct ip_set_req_adt),
|
||||
@@ -805,6 +869,7 @@ ip_set_create(const char *name,
|
||||
int res = 0;
|
||||
|
||||
DP("setname: %s, typename: %s, id: %u", name, typename, restore);
|
||||
|
||||
/*
|
||||
* First, and without any locks, allocate and initialize
|
||||
* a normal base set structure.
|
||||
@@ -848,6 +913,14 @@ ip_set_create(const char *name,
|
||||
}
|
||||
read_unlock_bh(&ip_set_lock);
|
||||
|
||||
/* Check request size */
|
||||
if (size != set->type->header_size) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
set->type->header_size,
|
||||
size);
|
||||
goto put_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Without holding any locks, create private part.
|
||||
*/
|
||||
@@ -1007,7 +1080,9 @@ ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index)
|
||||
u_int32_t from_ref;
|
||||
|
||||
DP("set: %s to %s", from->name, to->name);
|
||||
/* Features must not change. Artifical restriction. */
|
||||
/* Features must not change.
|
||||
* Not an artifical restriction anymore, as we must prevent
|
||||
* possible loops created by swapping in setlist type of sets. */
|
||||
if (from->type->features != to->type->features)
|
||||
return -ENOEXEC;
|
||||
|
||||
@@ -1916,6 +1991,7 @@ static struct nf_sockopt_ops so_set = {
|
||||
};
|
||||
|
||||
static int max_sets, hash_size;
|
||||
|
||||
module_param(max_sets, int, 0600);
|
||||
MODULE_PARM_DESC(max_sets, "maximal number of sets");
|
||||
module_param(hash_size, int, 0600);
|
||||
@@ -1958,6 +2034,7 @@ static int __init ip_set_init(void)
|
||||
vfree(ip_set_hash);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1975,7 +2052,10 @@ EXPORT_SYMBOL(ip_set_unregister_set_type);
|
||||
|
||||
EXPORT_SYMBOL(ip_set_get_byname);
|
||||
EXPORT_SYMBOL(ip_set_get_byindex);
|
||||
EXPORT_SYMBOL(ip_set_put);
|
||||
EXPORT_SYMBOL(ip_set_put_byindex);
|
||||
EXPORT_SYMBOL(ip_set_id);
|
||||
EXPORT_SYMBOL(__ip_set_get_byname);
|
||||
EXPORT_SYMBOL(__ip_set_put_byindex);
|
||||
|
||||
EXPORT_SYMBOL(ip_set_addip_kernel);
|
||||
EXPORT_SYMBOL(ip_set_delip_kernel);
|
||||
|
@@ -95,6 +95,9 @@ typedef uint16_t ip_set_id_t;
|
||||
#define IPSET_TYPE_PORT 0x02 /* Port type of set */
|
||||
#define IPSET_DATA_SINGLE 0x04 /* Single data storage */
|
||||
#define IPSET_DATA_DOUBLE 0x08 /* Double data storage */
|
||||
#define IPSET_DATA_TRIPLE 0x10 /* Triple data storage */
|
||||
#define IPSET_TYPE_IP1 0x20 /* IP address type of set */
|
||||
#define IPSET_TYPE_SETNAME 0x40 /* setname type of set */
|
||||
|
||||
/* Reserved keywords */
|
||||
#define IPSET_TOKEN_DEFAULT ":default:"
|
||||
@@ -304,7 +307,12 @@ static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
|
||||
return 4 * ((((b - a + 8) / 8) + 3) / 4);
|
||||
}
|
||||
|
||||
/* General limit for the elements in a set */
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include "ip_set_compat.h"
|
||||
#include "ip_set_malloc.h"
|
||||
|
||||
#define ip_set_printk(format, args...) \
|
||||
do { \
|
||||
@@ -487,20 +495,88 @@ struct ip_set_hash {
|
||||
|
||||
/* register and unregister set references */
|
||||
extern ip_set_id_t ip_set_get_byname(const char name[IP_SET_MAXNAMELEN]);
|
||||
extern ip_set_id_t ip_set_get_byindex(ip_set_id_t id);
|
||||
extern void ip_set_put(ip_set_id_t id);
|
||||
extern ip_set_id_t ip_set_get_byindex(ip_set_id_t index);
|
||||
extern void ip_set_put_byindex(ip_set_id_t index);
|
||||
extern ip_set_id_t ip_set_id(ip_set_id_t index);
|
||||
extern ip_set_id_t __ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
|
||||
struct ip_set **set);
|
||||
extern void __ip_set_put_byindex(ip_set_id_t index);
|
||||
|
||||
/* API for iptables set match, and SET target */
|
||||
extern void ip_set_addip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
extern void ip_set_delip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
extern int ip_set_addip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
extern int ip_set_delip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
extern int ip_set_testip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
|
||||
/* Macros to generate functions */
|
||||
|
||||
#define STRUCT(pre, type) CONCAT2(pre, type)
|
||||
#define CONCAT2(pre, type) struct pre##type
|
||||
|
||||
#define FNAME(pre, mid, post) CONCAT3(pre, mid, post)
|
||||
#define CONCAT3(pre, mid, post) pre##mid##post
|
||||
|
||||
#define UADT0(type, adt, args...) \
|
||||
static int \
|
||||
FNAME(type,_u,adt)(struct ip_set *set, const void *data, size_t size, \
|
||||
ip_set_ip_t *hash_ip) \
|
||||
{ \
|
||||
const STRUCT(ip_set_req_,type) *req = data; \
|
||||
\
|
||||
return FNAME(type,_,adt)(set, hash_ip , ## args); \
|
||||
}
|
||||
|
||||
#define UADT(type, adt, args...) \
|
||||
UADT0(type, adt, req->ip , ## args)
|
||||
|
||||
#define KADT(type, adt, getfn, args...) \
|
||||
static int \
|
||||
FNAME(type,_k,adt)(struct ip_set *set, \
|
||||
const struct sk_buff *skb, \
|
||||
ip_set_ip_t *hash_ip, \
|
||||
const u_int32_t *flags, \
|
||||
unsigned char index) \
|
||||
{ \
|
||||
ip_set_ip_t ip = getfn(skb, flags[index]); \
|
||||
\
|
||||
KADT_CONDITION \
|
||||
return FNAME(type,_,adt)(set, hash_ip, ip , ##args); \
|
||||
}
|
||||
|
||||
#define REGISTER_MODULE(type) \
|
||||
static int __init ip_set_##type##_init(void) \
|
||||
{ \
|
||||
init_max_page_size(); \
|
||||
return ip_set_register_set_type(&ip_set_##type); \
|
||||
} \
|
||||
\
|
||||
static void __exit ip_set_##type##_fini(void) \
|
||||
{ \
|
||||
/* FIXME: possible race with ip_set_create() */ \
|
||||
ip_set_unregister_set_type(&ip_set_##type); \
|
||||
} \
|
||||
\
|
||||
module_init(ip_set_##type##_init); \
|
||||
module_exit(ip_set_##type##_fini);
|
||||
|
||||
/* Common functions */
|
||||
|
||||
static inline ip_set_ip_t
|
||||
ipaddr(const struct sk_buff *skb, u_int32_t flag)
|
||||
{
|
||||
return ntohl(flag & IPSET_SRC ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr);
|
||||
}
|
||||
|
||||
#define jhash_ip(map, i, ip) jhash_1word(ip, *(map->initval + i))
|
||||
|
||||
#define pack_ip_port(map, ip, port) \
|
||||
(port + ((ip - ((map)->first_ip)) << 16))
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_H*/
|
||||
|
121
extensions/ipset/ip_set_bitmaps.h
Normal file
121
extensions/ipset/ip_set_bitmaps.h
Normal file
@@ -0,0 +1,121 @@
|
||||
#ifndef __IP_SET_BITMAPS_H
|
||||
#define __IP_SET_BITMAPS_H
|
||||
|
||||
/* Macros to generate functions */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define BITMAP_CREATE(type) \
|
||||
static int \
|
||||
type##_create(struct ip_set *set, const void *data, size_t size) \
|
||||
{ \
|
||||
int newbytes; \
|
||||
const struct ip_set_req_##type##_create *req = data; \
|
||||
struct ip_set_##type *map; \
|
||||
\
|
||||
if (req->from > req->to) { \
|
||||
DP("bad range"); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
\
|
||||
map = kmalloc(sizeof(struct ip_set_##type), GFP_KERNEL); \
|
||||
if (!map) { \
|
||||
DP("out of memory for %d bytes", \
|
||||
sizeof(struct ip_set_#type)); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
map->first_ip = req->from; \
|
||||
map->last_ip = req->to; \
|
||||
\
|
||||
newbytes = __##type##_create(req, map); \
|
||||
if (newbytes < 0) { \
|
||||
kfree(map); \
|
||||
return newbytes; \
|
||||
} \
|
||||
\
|
||||
map->size = newbytes; \
|
||||
map->members = ip_set_malloc(newbytes); \
|
||||
if (!map->members) { \
|
||||
DP("out of memory for %d bytes", newbytes); \
|
||||
kfree(map); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
memset(map->members, 0, newbytes); \
|
||||
\
|
||||
set->data = map; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define BITMAP_DESTROY(type) \
|
||||
static void \
|
||||
type##_destroy(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
ip_set_free(map->members, map->size); \
|
||||
kfree(map); \
|
||||
\
|
||||
set->data = NULL; \
|
||||
}
|
||||
|
||||
#define BITMAP_FLUSH(type) \
|
||||
static void \
|
||||
type##_flush(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
memset(map->members, 0, map->size); \
|
||||
}
|
||||
|
||||
#define BITMAP_LIST_HEADER(type) \
|
||||
static void \
|
||||
type##_list_header(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
struct ip_set_req_##type##_create *header = data; \
|
||||
\
|
||||
header->from = map->first_ip; \
|
||||
header->to = map->last_ip; \
|
||||
__##type##_list_header(map, header); \
|
||||
}
|
||||
|
||||
#define BITMAP_LIST_MEMBERS_SIZE(type) \
|
||||
static int \
|
||||
type##_list_members_size(const struct ip_set *set) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
return map->size; \
|
||||
}
|
||||
|
||||
#define BITMAP_LIST_MEMBERS(type) \
|
||||
static void \
|
||||
type##_list_members(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
memcpy(data, map->members, map->size); \
|
||||
}
|
||||
|
||||
#define IP_SET_TYPE(type, __features) \
|
||||
struct ip_set_type ip_set_##type = { \
|
||||
.typename = #type, \
|
||||
.features = __features, \
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION, \
|
||||
.create = &type##_create, \
|
||||
.destroy = &type##_destroy, \
|
||||
.flush = &type##_flush, \
|
||||
.reqsize = sizeof(struct ip_set_req_##type), \
|
||||
.addip = &type##_uadd, \
|
||||
.addip_kernel = &type##_kadd, \
|
||||
.delip = &type##_udel, \
|
||||
.delip_kernel = &type##_kdel, \
|
||||
.testip = &type##_utest, \
|
||||
.testip_kernel = &type##_ktest, \
|
||||
.header_size = sizeof(struct ip_set_req_##type##_create),\
|
||||
.list_header = &type##_list_header, \
|
||||
.list_members_size = &type##_list_members_size, \
|
||||
.list_members = &type##_list_members, \
|
||||
.me = THIS_MODULE, \
|
||||
};
|
||||
#endif /* __KERNEL */
|
||||
|
||||
#endif /* __IP_SET_BITMAPS_H */
|
70
extensions/ipset/ip_set_compat.h
Normal file
70
extensions/ipset/ip_set_compat.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef _IP_SET_COMPAT_H
|
||||
#define _IP_SET_COMPAT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/version.h>
|
||||
|
||||
/* Arrgh */
|
||||
#ifdef MODULE
|
||||
#define __MOD_INC(foo) __MOD_INC_USE_COUNT(foo)
|
||||
#define __MOD_DEC(foo) __MOD_DEC_USE_COUNT(foo)
|
||||
#else
|
||||
#define __MOD_INC(foo) 1
|
||||
#define __MOD_DEC(foo)
|
||||
#endif
|
||||
|
||||
/* Backward compatibility */
|
||||
#ifndef __nocast
|
||||
#define __nocast
|
||||
#endif
|
||||
#ifndef __bitwise__
|
||||
#define __bitwise__
|
||||
#endif
|
||||
|
||||
/* Compatibility glue code */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
#include <linux/interrupt.h>
|
||||
#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
|
||||
#define try_module_get(x) __MOD_INC(x)
|
||||
#define module_put(x) __MOD_DEC(x)
|
||||
#define __clear_bit(nr, addr) clear_bit(nr, addr)
|
||||
#define __set_bit(nr, addr) set_bit(nr, addr)
|
||||
#define __test_and_set_bit(nr, addr) test_and_set_bit(nr, addr)
|
||||
#define __test_and_clear_bit(nr, addr) test_and_clear_bit(nr, addr)
|
||||
|
||||
typedef unsigned __bitwise__ gfp_t;
|
||||
|
||||
static inline void *kzalloc(size_t size, gfp_t flags)
|
||||
{
|
||||
void *data = kmalloc(size, flags);
|
||||
|
||||
if (data)
|
||||
memset(data, 0, size);
|
||||
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
|
||||
#define __KMEM_CACHE_T__ kmem_cache_t
|
||||
#else
|
||||
#define __KMEM_CACHE_T__ struct kmem_cache
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
|
||||
#define ip_hdr(skb) ((skb)->nh.iph)
|
||||
#define skb_mac_header(skb) ((skb)->mac.raw)
|
||||
#define eth_hdr(skb) ((struct ethhdr *)skb_mac_header(skb))
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
|
||||
#define KMEM_CACHE_CREATE(name, size) \
|
||||
kmem_cache_create(name, size, 0, 0, NULL, NULL)
|
||||
#else
|
||||
#define KMEM_CACHE_CREATE(name, size) \
|
||||
kmem_cache_create(name, size, 0, 0, NULL)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _IP_SET_COMPAT_H */
|
48
extensions/ipset/ip_set_getport.h
Normal file
48
extensions/ipset/ip_set_getport.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef _IP_SET_GETPORT_H
|
||||
#define _IP_SET_GETPORT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define INVALID_PORT (MAX_RANGE + 1)
|
||||
|
||||
/* We must handle non-linear skbs */
|
||||
static inline ip_set_ip_t
|
||||
get_port(const struct sk_buff *skb, u_int32_t flags)
|
||||
{
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
switch (iph->protocol) {
|
||||
case IPPROTO_TCP: {
|
||||
struct tcphdr tcph;
|
||||
|
||||
/* See comments at tcp_match in ip_tables.c */
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags & IPSET_SRC ?
|
||||
tcph.source : tcph.dest);
|
||||
}
|
||||
case IPPROTO_UDP: {
|
||||
struct udphdr udph;
|
||||
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags & IPSET_SRC ?
|
||||
udph.source : udph.dest);
|
||||
}
|
||||
default:
|
||||
return INVALID_PORT;
|
||||
}
|
||||
}
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_GETPORT_H*/
|
304
extensions/ipset/ip_set_hashes.h
Normal file
304
extensions/ipset/ip_set_hashes.h
Normal file
@@ -0,0 +1,304 @@
|
||||
#ifndef __IP_SET_HASHES_H
|
||||
#define __IP_SET_HASHES_H
|
||||
|
||||
#define initval_t uint32_t
|
||||
|
||||
/* Macros to generate functions */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define HASH_RETRY0(type, dtype, cond) \
|
||||
static int \
|
||||
type##_retry(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data, *tmp; \
|
||||
dtype *elem; \
|
||||
void *members; \
|
||||
u_int32_t i, hashsize = map->hashsize; \
|
||||
int res; \
|
||||
\
|
||||
if (map->resize == 0) \
|
||||
return -ERANGE; \
|
||||
\
|
||||
again: \
|
||||
res = 0; \
|
||||
\
|
||||
/* Calculate new hash size */ \
|
||||
hashsize += (hashsize * map->resize)/100; \
|
||||
if (hashsize == map->hashsize) \
|
||||
hashsize++; \
|
||||
\
|
||||
ip_set_printk("rehashing of set %s triggered: " \
|
||||
"hashsize grows from %u to %u", \
|
||||
set->name, map->hashsize, hashsize); \
|
||||
\
|
||||
tmp = kmalloc(sizeof(struct ip_set_##type) \
|
||||
+ map->probes * sizeof(initval_t), GFP_ATOMIC); \
|
||||
if (!tmp) { \
|
||||
DP("out of memory for %d bytes", \
|
||||
sizeof(struct ip_set_##type) \
|
||||
+ map->probes * sizeof(initval_t)); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
tmp->members = harray_malloc(hashsize, sizeof(dtype), GFP_ATOMIC);\
|
||||
if (!tmp->members) { \
|
||||
DP("out of memory for %d bytes", hashsize * sizeof(dtype));\
|
||||
kfree(tmp); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
tmp->hashsize = hashsize; \
|
||||
tmp->elements = 0; \
|
||||
tmp->probes = map->probes; \
|
||||
tmp->resize = map->resize; \
|
||||
memcpy(tmp->initval, map->initval, map->probes * sizeof(initval_t));\
|
||||
__##type##_retry(tmp, map); \
|
||||
\
|
||||
write_lock_bh(&set->lock); \
|
||||
map = set->data; /* Play safe */ \
|
||||
for (i = 0; i < map->hashsize && res == 0; i++) { \
|
||||
elem = HARRAY_ELEM(map->members, dtype *, i); \
|
||||
if (cond) \
|
||||
res = __##type##_add(tmp, elem); \
|
||||
} \
|
||||
if (res) { \
|
||||
/* Failure, try again */ \
|
||||
write_unlock_bh(&set->lock); \
|
||||
harray_free(tmp->members); \
|
||||
kfree(tmp); \
|
||||
goto again; \
|
||||
} \
|
||||
\
|
||||
/* Success at resizing! */ \
|
||||
members = map->members; \
|
||||
\
|
||||
map->hashsize = tmp->hashsize; \
|
||||
map->members = tmp->members; \
|
||||
write_unlock_bh(&set->lock); \
|
||||
\
|
||||
harray_free(members); \
|
||||
kfree(tmp); \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define HASH_RETRY(type, dtype) \
|
||||
HASH_RETRY0(type, dtype, *elem)
|
||||
|
||||
#define HASH_RETRY2(type, dtype) \
|
||||
HASH_RETRY0(type, dtype, elem->ip || elem->ip1)
|
||||
|
||||
#define HASH_CREATE(type, dtype) \
|
||||
static int \
|
||||
type##_create(struct ip_set *set, const void *data, size_t size) \
|
||||
{ \
|
||||
const struct ip_set_req_##type##_create *req = data; \
|
||||
struct ip_set_##type *map; \
|
||||
uint16_t i; \
|
||||
\
|
||||
if (req->hashsize < 1) { \
|
||||
ip_set_printk("hashsize too small"); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
\
|
||||
if (req->probes < 1) { \
|
||||
ip_set_printk("probes too small"); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
\
|
||||
map = kmalloc(sizeof(struct ip_set_##type) \
|
||||
+ req->probes * sizeof(initval_t), GFP_KERNEL); \
|
||||
if (!map) { \
|
||||
DP("out of memory for %d bytes", \
|
||||
sizeof(struct ip_set_##type) \
|
||||
+ req->probes * sizeof(initval_t)); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
for (i = 0; i < req->probes; i++) \
|
||||
get_random_bytes(((initval_t *) map->initval)+i, 4); \
|
||||
map->elements = 0; \
|
||||
map->hashsize = req->hashsize; \
|
||||
map->probes = req->probes; \
|
||||
map->resize = req->resize; \
|
||||
if (__##type##_create(req, map)) { \
|
||||
kfree(map); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
map->members = harray_malloc(map->hashsize, sizeof(dtype), GFP_KERNEL);\
|
||||
if (!map->members) { \
|
||||
DP("out of memory for %d bytes", map->hashsize * sizeof(dtype));\
|
||||
kfree(map); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
\
|
||||
set->data = map; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define HASH_DESTROY(type) \
|
||||
static void \
|
||||
type##_destroy(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
harray_free(map->members); \
|
||||
kfree(map); \
|
||||
\
|
||||
set->data = NULL; \
|
||||
}
|
||||
|
||||
#define HASH_FLUSH(type, dtype) \
|
||||
static void \
|
||||
type##_flush(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
harray_flush(map->members, map->hashsize, sizeof(dtype)); \
|
||||
map->elements = 0; \
|
||||
}
|
||||
|
||||
#define HASH_FLUSH_CIDR(type, dtype) \
|
||||
static void \
|
||||
type##_flush(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
harray_flush(map->members, map->hashsize, sizeof(dtype)); \
|
||||
memset(map->cidr, 0, sizeof(map->cidr)); \
|
||||
memset(map->nets, 0, sizeof(map->nets)); \
|
||||
map->elements = 0; \
|
||||
}
|
||||
|
||||
#define HASH_LIST_HEADER(type) \
|
||||
static void \
|
||||
type##_list_header(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
struct ip_set_req_##type##_create *header = data; \
|
||||
\
|
||||
header->hashsize = map->hashsize; \
|
||||
header->probes = map->probes; \
|
||||
header->resize = map->resize; \
|
||||
__##type##_list_header(map, header); \
|
||||
}
|
||||
|
||||
#define HASH_LIST_MEMBERS_SIZE(type, dtype) \
|
||||
static int \
|
||||
type##_list_members_size(const struct ip_set *set) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
return (map->hashsize * sizeof(dtype)); \
|
||||
}
|
||||
|
||||
#define HASH_LIST_MEMBERS(type, dtype) \
|
||||
static void \
|
||||
type##_list_members(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
dtype *elem; \
|
||||
uint32_t i; \
|
||||
\
|
||||
for (i = 0; i < map->hashsize; i++) { \
|
||||
elem = HARRAY_ELEM(map->members, dtype *, i); \
|
||||
((dtype *)data)[i] = *elem; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define HASH_LIST_MEMBERS_MEMCPY(type, dtype) \
|
||||
static void \
|
||||
type##_list_members(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
dtype *elem; \
|
||||
uint32_t i; \
|
||||
\
|
||||
for (i = 0; i < map->hashsize; i++) { \
|
||||
elem = HARRAY_ELEM(map->members, dtype *, i); \
|
||||
memcpy((((dtype *)data)+i), elem, sizeof(dtype)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define IP_SET_RTYPE(type, __features) \
|
||||
struct ip_set_type ip_set_##type = { \
|
||||
.typename = #type, \
|
||||
.features = __features, \
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION, \
|
||||
.create = &type##_create, \
|
||||
.retry = &type##_retry, \
|
||||
.destroy = &type##_destroy, \
|
||||
.flush = &type##_flush, \
|
||||
.reqsize = sizeof(struct ip_set_req_##type), \
|
||||
.addip = &type##_uadd, \
|
||||
.addip_kernel = &type##_kadd, \
|
||||
.delip = &type##_udel, \
|
||||
.delip_kernel = &type##_kdel, \
|
||||
.testip = &type##_utest, \
|
||||
.testip_kernel = &type##_ktest, \
|
||||
.header_size = sizeof(struct ip_set_req_##type##_create),\
|
||||
.list_header = &type##_list_header, \
|
||||
.list_members_size = &type##_list_members_size, \
|
||||
.list_members = &type##_list_members, \
|
||||
.me = THIS_MODULE, \
|
||||
};
|
||||
|
||||
/* Helper functions */
|
||||
static inline void
|
||||
add_cidr_size(uint8_t *cidr, uint8_t size)
|
||||
{
|
||||
uint8_t next;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && cidr[i]; i++) {
|
||||
if (cidr[i] < size) {
|
||||
next = cidr[i];
|
||||
cidr[i] = size;
|
||||
size = next;
|
||||
}
|
||||
}
|
||||
if (i < 30)
|
||||
cidr[i] = size;
|
||||
}
|
||||
|
||||
static inline void
|
||||
del_cidr_size(uint8_t *cidr, uint8_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 29 && cidr[i]; i++) {
|
||||
if (cidr[i] == size)
|
||||
cidr[i] = size = cidr[i+1];
|
||||
}
|
||||
cidr[29] = 0;
|
||||
}
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif /* __KERNEL */
|
||||
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX 65535
|
||||
#endif
|
||||
|
||||
static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
|
||||
|
||||
static inline ip_set_ip_t
|
||||
pack_ip_cidr(ip_set_ip_t ip, unsigned char cidr)
|
||||
{
|
||||
ip_set_ip_t addr, *paddr = &addr;
|
||||
unsigned char n, t, *a;
|
||||
|
||||
addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
|
||||
#ifdef __KERNEL__
|
||||
DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
|
||||
#endif
|
||||
n = cidr / 8;
|
||||
t = cidr % 8;
|
||||
a = &((unsigned char *)paddr)[n];
|
||||
*a = *a /(1 << (8 - t)) + shifts[t];
|
||||
#ifdef __KERNEL__
|
||||
DP("n: %u, t: %u, a: %u", n, t, *a);
|
||||
DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
|
||||
HIPQUAD(ip), cidr, NIPQUAD(addr));
|
||||
#endif
|
||||
|
||||
return ntohl(addr);
|
||||
}
|
||||
|
||||
|
||||
#endif /* __IP_SET_HASHES_H */
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
/* Copyright (C) 2003-2008 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
|
||||
@@ -8,34 +8,24 @@
|
||||
/* Kernel module implementing an ip hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include "ip_set.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_malloc.h"
|
||||
#include "ip_set_iphash.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
static inline __u32
|
||||
jhash_ip(const struct ip_set_iphash *map, uint16_t i, ip_set_ip_t ip)
|
||||
{
|
||||
return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
|
||||
}
|
||||
|
||||
static inline __u32
|
||||
hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
iphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
__u32 id;
|
||||
@@ -59,64 +49,30 @@ hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
}
|
||||
|
||||
static inline int
|
||||
__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
iphash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
return (ip && hash_id(set, ip, hash_ip) != UINT_MAX);
|
||||
return (ip && iphash_id(set, hash_ip, ip) != UINT_MAX);
|
||||
}
|
||||
|
||||
static int
|
||||
testip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_iphash *req = data;
|
||||
#define KADT_CONDITION
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iphash)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_iphash),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __testip(set, req->ip, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
testip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
return __testip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
}
|
||||
UADT(iphash, test)
|
||||
KADT(iphash, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
__iphash_add(struct ip_set_iphash *map, ip_set_ip_t *ip)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
if (!ip || map->elements >= limit)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = ip & map->netmask;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip(map, i, *hash_ip) % map->hashsize;
|
||||
probe = jhash_ip(map, i, *ip) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
|
||||
if (*elem == *hash_ip)
|
||||
if (*elem == *ip)
|
||||
return -EEXIST;
|
||||
if (!*elem) {
|
||||
*elem = *hash_ip;
|
||||
*elem = *ip;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
@@ -125,115 +81,32 @@ __addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static int
|
||||
addip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_iphash *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iphash)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_iphash),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __addip(set->data, req->ip, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
addip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
return __addip((struct ip_set_iphash *) set->data,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
}
|
||||
|
||||
static int retry(struct ip_set *set)
|
||||
static inline int
|
||||
iphash_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
ip_set_ip_t hash_ip, *elem;
|
||||
void *members;
|
||||
u_int32_t i, hashsize = map->hashsize;
|
||||
int res;
|
||||
struct ip_set_iphash *tmp;
|
||||
|
||||
if (map->resize == 0)
|
||||
if (!ip || map->elements >= limit)
|
||||
return -ERANGE;
|
||||
|
||||
again:
|
||||
res = 0;
|
||||
|
||||
/* Calculate new hash size */
|
||||
hashsize += (hashsize * map->resize)/100;
|
||||
if (hashsize == map->hashsize)
|
||||
hashsize++;
|
||||
*hash_ip = ip & map->netmask;
|
||||
|
||||
ip_set_printk("rehashing of set %s triggered: "
|
||||
"hashsize grows from %u to %u",
|
||||
set->name, map->hashsize, hashsize);
|
||||
|
||||
tmp = kmalloc(sizeof(struct ip_set_iphash)
|
||||
+ map->probes * sizeof(uint32_t), GFP_ATOMIC);
|
||||
if (!tmp) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_iphash)
|
||||
+ map->probes * sizeof(uint32_t));
|
||||
return -ENOMEM;
|
||||
}
|
||||
tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
|
||||
if (!tmp->members) {
|
||||
DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
|
||||
kfree(tmp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
tmp->hashsize = hashsize;
|
||||
tmp->elements = 0;
|
||||
tmp->probes = map->probes;
|
||||
tmp->resize = map->resize;
|
||||
tmp->netmask = map->netmask;
|
||||
memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
|
||||
|
||||
write_lock_bh(&set->lock);
|
||||
map = set->data; /* Play safe */
|
||||
for (i = 0; i < map->hashsize && res == 0; i++) {
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
|
||||
if (*elem)
|
||||
res = __addip(tmp, *elem, &hash_ip);
|
||||
}
|
||||
if (res) {
|
||||
/* Failure, try again */
|
||||
write_unlock_bh(&set->lock);
|
||||
harray_free(tmp->members);
|
||||
kfree(tmp);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Success at resizing! */
|
||||
members = map->members;
|
||||
|
||||
map->hashsize = tmp->hashsize;
|
||||
map->members = tmp->members;
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
harray_free(members);
|
||||
kfree(tmp);
|
||||
|
||||
return 0;
|
||||
return __iphash_add(map, hash_ip);
|
||||
}
|
||||
|
||||
UADT(iphash, add)
|
||||
KADT(iphash, add, ipaddr)
|
||||
|
||||
static inline void
|
||||
__iphash_retry(struct ip_set_iphash *tmp, struct ip_set_iphash *map)
|
||||
{
|
||||
tmp->netmask = map->netmask;
|
||||
}
|
||||
|
||||
HASH_RETRY(iphash, ip_set_ip_t)
|
||||
|
||||
static inline int
|
||||
__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
iphash_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
ip_set_ip_t id, *elem;
|
||||
@@ -241,7 +114,7 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
|
||||
id = hash_id(set, ip, hash_ip);
|
||||
id = iphash_id(set, hash_ip, ip);
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
@@ -252,156 +125,35 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
delip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
UADT(iphash, del)
|
||||
KADT(iphash, del, ipaddr)
|
||||
|
||||
static inline int
|
||||
__iphash_create(const struct ip_set_req_iphash_create *req,
|
||||
struct ip_set_iphash *map)
|
||||
{
|
||||
const struct ip_set_req_iphash *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iphash)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_iphash),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __delip(set, req->ip, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
delip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
return __delip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
}
|
||||
|
||||
static int create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
const struct ip_set_req_iphash_create *req = data;
|
||||
struct ip_set_iphash *map;
|
||||
uint16_t i;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iphash_create)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_iphash_create),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (req->hashsize < 1) {
|
||||
ip_set_printk("hashsize too small");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (req->probes < 1) {
|
||||
ip_set_printk("probes too small");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_iphash)
|
||||
+ req->probes * sizeof(uint32_t), GFP_KERNEL);
|
||||
if (!map) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_iphash)
|
||||
+ req->probes * sizeof(uint32_t));
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (i = 0; i < req->probes; i++)
|
||||
get_random_bytes(((uint32_t *) map->initval)+i, 4);
|
||||
map->elements = 0;
|
||||
map->hashsize = req->hashsize;
|
||||
map->probes = req->probes;
|
||||
map->resize = req->resize;
|
||||
map->netmask = req->netmask;
|
||||
map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
|
||||
if (!map->members) {
|
||||
DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set->data = map;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
HASH_CREATE(iphash, ip_set_ip_t)
|
||||
HASH_DESTROY(iphash)
|
||||
|
||||
harray_free(map->members);
|
||||
kfree(map);
|
||||
HASH_FLUSH(iphash, ip_set_ip_t)
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
|
||||
map->elements = 0;
|
||||
}
|
||||
|
||||
static void list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
struct ip_set_req_iphash_create *header = data;
|
||||
|
||||
header->hashsize = map->hashsize;
|
||||
header->probes = map->probes;
|
||||
header->resize = map->resize;
|
||||
static inline void
|
||||
__iphash_list_header(const struct ip_set_iphash *map,
|
||||
struct ip_set_req_iphash_create *header)
|
||||
{
|
||||
header->netmask = map->netmask;
|
||||
}
|
||||
|
||||
static int list_members_size(const struct ip_set *set)
|
||||
{
|
||||
const struct ip_set_iphash *map = set->data;
|
||||
HASH_LIST_HEADER(iphash)
|
||||
HASH_LIST_MEMBERS_SIZE(iphash, ip_set_ip_t)
|
||||
HASH_LIST_MEMBERS(iphash, ip_set_ip_t)
|
||||
|
||||
return (map->hashsize * sizeof(ip_set_ip_t));
|
||||
}
|
||||
|
||||
static void list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_iphash *map = set->data;
|
||||
ip_set_ip_t i, *elem;
|
||||
|
||||
for (i = 0; i < map->hashsize; i++) {
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
|
||||
((ip_set_ip_t *)data)[i] = *elem;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ip_set_type ip_set_iphash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
.create = &create,
|
||||
.destroy = &destroy,
|
||||
.flush = &flush,
|
||||
.reqsize = sizeof(struct ip_set_req_iphash),
|
||||
.addip = &addip,
|
||||
.addip_kernel = &addip_kernel,
|
||||
.retry = &retry,
|
||||
.delip = &delip,
|
||||
.delip_kernel = &delip_kernel,
|
||||
.testip = &testip,
|
||||
.testip_kernel = &testip_kernel,
|
||||
.header_size = sizeof(struct ip_set_req_iphash_create),
|
||||
.list_header = &list_header,
|
||||
.list_members_size = &list_members_size,
|
||||
.list_members = &list_members,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
IP_SET_RTYPE(iphash, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
@@ -409,17 +161,4 @@ MODULE_DESCRIPTION("iphash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
static int __init ip_set_iphash_init(void)
|
||||
{
|
||||
init_max_page_size();
|
||||
return ip_set_register_set_type(&ip_set_iphash);
|
||||
}
|
||||
|
||||
static void __exit ip_set_iphash_fini(void)
|
||||
{
|
||||
/* FIXME: possible race with ip_set_create() */
|
||||
ip_set_unregister_set_type(&ip_set_iphash);
|
||||
}
|
||||
|
||||
module_init(ip_set_iphash_init);
|
||||
module_exit(ip_set_iphash_fini);
|
||||
REGISTER_MODULE(iphash)
|
||||
|
@@ -2,9 +2,9 @@
|
||||
#define __IP_SET_IPHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "iphash"
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
|
||||
struct ip_set_iphash {
|
||||
ip_set_ip_t *members; /* the iphash proper */
|
||||
@@ -13,7 +13,7 @@ struct ip_set_iphash {
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t netmask; /* netmask */
|
||||
void *initval[0]; /* initvals for jhash_1word */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_iphash_create {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
* Copyright (C) 2003-2008 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
|
||||
@@ -12,9 +12,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include "ip_set.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
@@ -29,9 +26,9 @@ ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
|
||||
}
|
||||
|
||||
static inline int
|
||||
__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
ipmap_test(const struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_ipmap *map = set->data;
|
||||
const struct ip_set_ipmap *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
@@ -42,43 +39,13 @@ __testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
return !!test_bit(ip_to_id(map, *hash_ip), map->members);
|
||||
}
|
||||
|
||||
static int
|
||||
testip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_ipmap *req = data;
|
||||
#define KADT_CONDITION
|
||||
|
||||
if (size != sizeof(struct ip_set_req_ipmap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_ipmap),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __testip(set, req->ip, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
testip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
int res = __testip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
return (res < 0 ? 0 : res);
|
||||
}
|
||||
UADT(ipmap, test)
|
||||
KADT(ipmap, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__addip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
ipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_ipmap *map = set->data;
|
||||
|
||||
@@ -93,43 +60,11 @@ __addip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
addip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_ipmap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_ipmap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_ipmap),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
DP("%u.%u.%u.%u", HIPQUAD(req->ip));
|
||||
return __addip(set, req->ip, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
addip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
return __addip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
}
|
||||
UADT(ipmap, add)
|
||||
KADT(ipmap, add, ipaddr)
|
||||
|
||||
static inline int
|
||||
__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
ipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_ipmap *map = set->data;
|
||||
|
||||
@@ -144,69 +79,13 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
delip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
UADT(ipmap, del)
|
||||
KADT(ipmap, del, ipaddr)
|
||||
|
||||
static inline int
|
||||
__ipmap_create(const struct ip_set_req_ipmap_create *req,
|
||||
struct ip_set_ipmap *map)
|
||||
{
|
||||
const struct ip_set_req_ipmap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_ipmap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_ipmap),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __delip(set, req->ip, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
delip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
return __delip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
}
|
||||
|
||||
static int create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
int newbytes;
|
||||
const struct ip_set_req_ipmap_create *req = data;
|
||||
struct ip_set_ipmap *map;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_ipmap_create)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_ipmap_create),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DP("from %u.%u.%u.%u to %u.%u.%u.%u",
|
||||
HIPQUAD(req->from), HIPQUAD(req->to));
|
||||
|
||||
if (req->from > req->to) {
|
||||
DP("bad ip range");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
|
||||
if (!map) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_ipmap));
|
||||
return -ENOMEM;
|
||||
}
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
map->netmask = req->netmask;
|
||||
|
||||
if (req->netmask == 0xFFFFFFFF) {
|
||||
@@ -215,12 +94,12 @@ static int create(struct ip_set *set, const void *data, size_t size)
|
||||
} else {
|
||||
unsigned int mask_bits, netmask_bits;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
|
||||
map->first_ip &= map->netmask; /* Should we better bark? */
|
||||
|
||||
|
||||
mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
|
||||
netmask_bits = mask_to_bits(map->netmask);
|
||||
|
||||
|
||||
if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF))
|
||||
|| netmask_bits <= mask_bits)
|
||||
return -ENOEXEC;
|
||||
@@ -231,101 +110,33 @@ static int create(struct ip_set *set, const void *data, size_t size)
|
||||
map->sizeid = 2 << (netmask_bits - mask_bits - 1);
|
||||
}
|
||||
if (map->sizeid > MAX_RANGE + 1) {
|
||||
ip_set_printk("range too big (max %d addresses)",
|
||||
MAX_RANGE+1);
|
||||
kfree(map);
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
map->sizeid, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
DP("hosts %u, sizeid %u", map->hosts, map->sizeid);
|
||||
newbytes = bitmap_bytes(0, map->sizeid - 1);
|
||||
map->members = kmalloc(newbytes, GFP_KERNEL);
|
||||
if (!map->members) {
|
||||
DP("out of memory for %d bytes", newbytes);
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(map->members, 0, newbytes);
|
||||
|
||||
set->data = map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_ipmap *map = set->data;
|
||||
|
||||
kfree(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_ipmap *map = set->data;
|
||||
memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
|
||||
}
|
||||
|
||||
static void list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_ipmap *map = set->data;
|
||||
struct ip_set_req_ipmap_create *header = data;
|
||||
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
header->netmask = map->netmask;
|
||||
}
|
||||
|
||||
static int list_members_size(const struct ip_set *set)
|
||||
{
|
||||
const struct ip_set_ipmap *map = set->data;
|
||||
|
||||
return bitmap_bytes(0, map->sizeid - 1);
|
||||
}
|
||||
|
||||
static void list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_ipmap *map = set->data;
|
||||
int bytes = bitmap_bytes(0, map->sizeid - 1);
|
||||
BITMAP_CREATE(ipmap)
|
||||
BITMAP_DESTROY(ipmap)
|
||||
BITMAP_FLUSH(ipmap)
|
||||
|
||||
memcpy(data, map->members, bytes);
|
||||
static inline void
|
||||
__ipmap_list_header(const struct ip_set_ipmap *map,
|
||||
struct ip_set_req_ipmap_create *header)
|
||||
{
|
||||
header->netmask = map->netmask;
|
||||
}
|
||||
|
||||
static struct ip_set_type ip_set_ipmap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
.create = &create,
|
||||
.destroy = &destroy,
|
||||
.flush = &flush,
|
||||
.reqsize = sizeof(struct ip_set_req_ipmap),
|
||||
.addip = &addip,
|
||||
.addip_kernel = &addip_kernel,
|
||||
.delip = &delip,
|
||||
.delip_kernel = &delip_kernel,
|
||||
.testip = &testip,
|
||||
.testip_kernel = &testip_kernel,
|
||||
.header_size = sizeof(struct ip_set_req_ipmap_create),
|
||||
.list_header = &list_header,
|
||||
.list_members_size = &list_members_size,
|
||||
.list_members = &list_members,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
BITMAP_LIST_HEADER(ipmap)
|
||||
BITMAP_LIST_MEMBERS_SIZE(ipmap)
|
||||
BITMAP_LIST_MEMBERS(ipmap)
|
||||
|
||||
IP_SET_TYPE(ipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipmap type of IP sets");
|
||||
|
||||
static int __init ip_set_ipmap_init(void)
|
||||
{
|
||||
return ip_set_register_set_type(&ip_set_ipmap);
|
||||
}
|
||||
|
||||
static void __exit ip_set_ipmap_fini(void)
|
||||
{
|
||||
/* FIXME: possible race with ip_set_create() */
|
||||
ip_set_unregister_set_type(&ip_set_ipmap);
|
||||
}
|
||||
|
||||
module_init(ip_set_ipmap_init);
|
||||
module_exit(ip_set_ipmap_fini);
|
||||
REGISTER_MODULE(ipmap)
|
||||
|
@@ -2,9 +2,9 @@
|
||||
#define __IP_SET_IPMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
|
||||
#define SETTYPE_NAME "ipmap"
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
|
||||
struct ip_set_ipmap {
|
||||
void *members; /* the ipmap proper */
|
||||
@@ -13,6 +13,7 @@ struct ip_set_ipmap {
|
||||
ip_set_ip_t netmask; /* subnet netmask */
|
||||
ip_set_ip_t sizeid; /* size of set in IPs */
|
||||
ip_set_ip_t hosts; /* number of hosts in a subnet */
|
||||
size_t size; /* size of the ipmap proper */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipmap_create {
|
||||
@@ -25,7 +26,7 @@ struct ip_set_req_ipmap {
|
||||
ip_set_ip_t ip;
|
||||
};
|
||||
|
||||
static unsigned int
|
||||
static inline unsigned int
|
||||
mask_to_bits(ip_set_ip_t mask)
|
||||
{
|
||||
unsigned int bits = 32;
|
||||
@@ -35,19 +36,19 @@ mask_to_bits(ip_set_ip_t mask)
|
||||
return bits;
|
||||
|
||||
maskaddr = 0xFFFFFFFE;
|
||||
while (--bits >= 0 && maskaddr != mask)
|
||||
while (--bits > 0 && maskaddr != mask)
|
||||
maskaddr <<= 1;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static ip_set_ip_t
|
||||
static inline ip_set_ip_t
|
||||
range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
|
||||
{
|
||||
ip_set_ip_t mask = 0xFFFFFFFE;
|
||||
|
||||
*bits = 32;
|
||||
while (--(*bits) >= 0 && mask && (to & mask) != from)
|
||||
while (--(*bits) > 0 && mask && (to & mask) != from)
|
||||
mask <<= 1;
|
||||
|
||||
return mask;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
/* Copyright (C) 2003-2008 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
|
||||
@@ -8,100 +8,40 @@
|
||||
/* Kernel module implementing an ip+port hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include "ip_set.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_malloc.h"
|
||||
#include "ip_set_ipporthash.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
/* We must handle non-linear skbs */
|
||||
static inline ip_set_ip_t
|
||||
get_port(const struct sk_buff *skb, u_int32_t flags)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
#else
|
||||
struct iphdr *iph = skb->nh.iph;
|
||||
#endif
|
||||
u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
|
||||
switch (iph->protocol) {
|
||||
case IPPROTO_TCP: {
|
||||
struct tcphdr tcph;
|
||||
|
||||
/* See comments at tcp_match in ip_tables.c */
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
|
||||
#else
|
||||
if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
|
||||
#endif
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags & IPSET_SRC ?
|
||||
tcph.source : tcph.dest);
|
||||
}
|
||||
case IPPROTO_UDP: {
|
||||
struct udphdr udph;
|
||||
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
|
||||
#else
|
||||
if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
|
||||
#endif
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags & IPSET_SRC ?
|
||||
udph.source : udph.dest);
|
||||
}
|
||||
default:
|
||||
return INVALID_PORT;
|
||||
}
|
||||
}
|
||||
|
||||
static inline __u32
|
||||
jhash_ip(const struct ip_set_ipporthash *map, uint16_t i, ip_set_ip_t ip)
|
||||
{
|
||||
return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
|
||||
}
|
||||
|
||||
#define HASH_IP(map, ip, port) (port + ((ip - ((map)->first_ip)) << 16))
|
||||
|
||||
static inline __u32
|
||||
hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t *hash_ip)
|
||||
ipporthash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
*hash_ip = HASH_IP(map, ip, port);
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
|
||||
DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
|
||||
if (!*hash_ip)
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip(map, i, *hash_ip) % map->hashsize;
|
||||
@@ -116,91 +56,45 @@ hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
|
||||
}
|
||||
|
||||
static inline int
|
||||
__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t *hash_ip)
|
||||
ipporthash_test(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (hash_id(set, ip, port, hash_ip) != UINT_MAX);
|
||||
return (ipporthash_id(set, hash_ip, ip, port) != UINT_MAX);
|
||||
}
|
||||
|
||||
static int
|
||||
testip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_ipporthash *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_ipporthash)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_ipporthash),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __testip(set, req->ip, req->port, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
testip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
ip_set_ip_t port;
|
||||
int res;
|
||||
|
||||
if (flags[index+1] == 0)
|
||||
#define KADT_CONDITION \
|
||||
ip_set_ip_t port; \
|
||||
\
|
||||
if (flags[index+1] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, flags[index+1]); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
port = get_port(skb, flags[index+1]);
|
||||
|
||||
DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
|
||||
flags[index] & IPSET_SRC ? "SRC" : "DST",
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
NIPQUAD(ip_hdr(skb)->saddr),
|
||||
NIPQUAD(ip_hdr(skb)->daddr));
|
||||
#else
|
||||
NIPQUAD(skb->nh.iph->saddr),
|
||||
NIPQUAD(skb->nh.iph->daddr));
|
||||
#endif
|
||||
DP("flag %s port %u",
|
||||
flags[index+1] & IPSET_SRC ? "SRC" : "DST",
|
||||
port);
|
||||
if (port == INVALID_PORT)
|
||||
return 0;
|
||||
|
||||
res = __testip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
port,
|
||||
hash_ip);
|
||||
return (res < 0 ? 0 : res);
|
||||
|
||||
}
|
||||
UADT(ipporthash, test, req->port)
|
||||
KADT(ipporthash, test, ipaddr, port)
|
||||
|
||||
static inline int
|
||||
__add_haship(struct ip_set_ipporthash *map, ip_set_ip_t hash_ip)
|
||||
__ipporthash_add(struct ip_set_ipporthash *map, ip_set_ip_t *ip)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip(map, i, hash_ip) % map->hashsize;
|
||||
probe = jhash_ip(map, i, *ip) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
|
||||
if (*elem == hash_ip)
|
||||
if (*elem == *ip)
|
||||
return -EEXIST;
|
||||
if (!*elem) {
|
||||
*elem = hash_ip;
|
||||
*elem = *ip;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
@@ -210,153 +104,39 @@ __add_haship(struct ip_set_ipporthash *map, ip_set_ip_t hash_ip)
|
||||
}
|
||||
|
||||
static inline int
|
||||
__addip(struct ip_set_ipporthash *map, ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t *hash_ip)
|
||||
ipporthash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
if (map->elements > limit)
|
||||
return -ERANGE;
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = HASH_IP(map, ip, port);
|
||||
|
||||
return __add_haship(map, *hash_ip);
|
||||
}
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
|
||||
static int
|
||||
addip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_ipporthash *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_ipporthash)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_ipporthash),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __addip(set->data, req->ip, req->port, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
addip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
ip_set_ip_t port;
|
||||
|
||||
if (flags[index+1] == 0)
|
||||
return -EINVAL;
|
||||
|
||||
port = get_port(skb, flags[index+1]);
|
||||
|
||||
DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
|
||||
flags[index] & IPSET_SRC ? "SRC" : "DST",
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
NIPQUAD(ip_hdr(skb)->saddr),
|
||||
NIPQUAD(ip_hdr(skb)->daddr));
|
||||
#else
|
||||
NIPQUAD(skb->nh.iph->saddr),
|
||||
NIPQUAD(skb->nh.iph->daddr));
|
||||
#endif
|
||||
DP("flag %s port %u",
|
||||
flags[index+1] & IPSET_SRC ? "SRC" : "DST",
|
||||
port);
|
||||
if (port == INVALID_PORT)
|
||||
return -EINVAL;
|
||||
|
||||
return __addip(set->data,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
port,
|
||||
hash_ip);
|
||||
}
|
||||
|
||||
static int retry(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
ip_set_ip_t *elem;
|
||||
void *members;
|
||||
u_int32_t i, hashsize = map->hashsize;
|
||||
int res;
|
||||
struct ip_set_ipporthash *tmp;
|
||||
|
||||
if (map->resize == 0)
|
||||
if (!*hash_ip)
|
||||
return -ERANGE;
|
||||
|
||||
again:
|
||||
res = 0;
|
||||
|
||||
/* Calculate new hash size */
|
||||
hashsize += (hashsize * map->resize)/100;
|
||||
if (hashsize == map->hashsize)
|
||||
hashsize++;
|
||||
|
||||
ip_set_printk("rehashing of set %s triggered: "
|
||||
"hashsize grows from %u to %u",
|
||||
set->name, map->hashsize, hashsize);
|
||||
return __ipporthash_add(map, hash_ip);
|
||||
}
|
||||
|
||||
tmp = kmalloc(sizeof(struct ip_set_ipporthash)
|
||||
+ map->probes * sizeof(uint32_t), GFP_ATOMIC);
|
||||
if (!tmp) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_ipporthash)
|
||||
+ map->probes * sizeof(uint32_t));
|
||||
return -ENOMEM;
|
||||
}
|
||||
tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
|
||||
if (!tmp->members) {
|
||||
DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
|
||||
kfree(tmp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
tmp->hashsize = hashsize;
|
||||
tmp->elements = 0;
|
||||
tmp->probes = map->probes;
|
||||
tmp->resize = map->resize;
|
||||
UADT(ipporthash, add, req->port)
|
||||
KADT(ipporthash, add, ipaddr, port)
|
||||
|
||||
static inline void
|
||||
__ipporthash_retry(struct ip_set_ipporthash *tmp,
|
||||
struct ip_set_ipporthash *map)
|
||||
{
|
||||
tmp->first_ip = map->first_ip;
|
||||
tmp->last_ip = map->last_ip;
|
||||
memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
|
||||
|
||||
write_lock_bh(&set->lock);
|
||||
map = set->data; /* Play safe */
|
||||
for (i = 0; i < map->hashsize && res == 0; i++) {
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
|
||||
if (*elem)
|
||||
res = __add_haship(tmp, *elem);
|
||||
}
|
||||
if (res) {
|
||||
/* Failure, try again */
|
||||
write_unlock_bh(&set->lock);
|
||||
harray_free(tmp->members);
|
||||
kfree(tmp);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Success at resizing! */
|
||||
members = map->members;
|
||||
|
||||
map->hashsize = tmp->hashsize;
|
||||
map->members = tmp->members;
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
harray_free(members);
|
||||
kfree(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_RETRY(ipporthash, ip_set_ip_t)
|
||||
|
||||
static inline int
|
||||
__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t *hash_ip)
|
||||
ipporthash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
ip_set_ip_t id;
|
||||
@@ -365,7 +145,7 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
id = hash_id(set, ip, port, hash_ip);
|
||||
id = ipporthash_id(set, hash_ip, ip, port);
|
||||
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
@@ -377,181 +157,40 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
delip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
UADT(ipporthash, del, req->port)
|
||||
KADT(ipporthash, del, ipaddr, port)
|
||||
|
||||
static inline int
|
||||
__ipporthash_create(const struct ip_set_req_ipporthash_create *req,
|
||||
struct ip_set_ipporthash *map)
|
||||
{
|
||||
const struct ip_set_req_ipporthash *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_ipporthash)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_ipporthash),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __delip(set, req->ip, req->port, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
delip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
ip_set_ip_t port;
|
||||
|
||||
if (flags[index+1] == 0)
|
||||
return -EINVAL;
|
||||
|
||||
port = get_port(skb, flags[index+1]);
|
||||
|
||||
DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
|
||||
flags[index] & IPSET_SRC ? "SRC" : "DST",
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
NIPQUAD(ip_hdr(skb)->saddr),
|
||||
NIPQUAD(ip_hdr(skb)->daddr));
|
||||
#else
|
||||
NIPQUAD(skb->nh.iph->saddr),
|
||||
NIPQUAD(skb->nh.iph->daddr));
|
||||
#endif
|
||||
DP("flag %s port %u",
|
||||
flags[index+1] & IPSET_SRC ? "SRC" : "DST",
|
||||
port);
|
||||
if (port == INVALID_PORT)
|
||||
return -EINVAL;
|
||||
|
||||
return __delip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
port,
|
||||
hash_ip);
|
||||
}
|
||||
|
||||
static int create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
const struct ip_set_req_ipporthash_create *req = data;
|
||||
struct ip_set_ipporthash *map;
|
||||
uint16_t i;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_ipporthash_create)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_ipporthash_create),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (req->hashsize < 1) {
|
||||
ip_set_printk("hashsize too small");
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (req->probes < 1) {
|
||||
ip_set_printk("probes too small");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_ipporthash)
|
||||
+ req->probes * sizeof(uint32_t), GFP_KERNEL);
|
||||
if (!map) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_ipporthash)
|
||||
+ req->probes * sizeof(uint32_t));
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (i = 0; i < req->probes; i++)
|
||||
get_random_bytes(((uint32_t *) map->initval)+i, 4);
|
||||
map->elements = 0;
|
||||
map->hashsize = req->hashsize;
|
||||
map->probes = req->probes;
|
||||
map->resize = req->resize;
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
|
||||
if (!map->members) {
|
||||
DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set->data = map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy(struct ip_set *set)
|
||||
HASH_CREATE(ipporthash, ip_set_ip_t)
|
||||
HASH_DESTROY(ipporthash)
|
||||
HASH_FLUSH(ipporthash, ip_set_ip_t)
|
||||
|
||||
static inline void
|
||||
__ipporthash_list_header(const struct ip_set_ipporthash *map,
|
||||
struct ip_set_req_ipporthash_create *header)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
|
||||
harray_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
|
||||
map->elements = 0;
|
||||
}
|
||||
|
||||
static void list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_ipporthash *map = set->data;
|
||||
struct ip_set_req_ipporthash_create *header = data;
|
||||
|
||||
header->hashsize = map->hashsize;
|
||||
header->probes = map->probes;
|
||||
header->resize = map->resize;
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
}
|
||||
|
||||
static int list_members_size(const struct ip_set *set)
|
||||
{
|
||||
const struct ip_set_ipporthash *map = set->data;
|
||||
HASH_LIST_HEADER(ipporthash)
|
||||
HASH_LIST_MEMBERS_SIZE(ipporthash, ip_set_ip_t)
|
||||
HASH_LIST_MEMBERS(ipporthash, ip_set_ip_t)
|
||||
|
||||
return (map->hashsize * sizeof(ip_set_ip_t));
|
||||
}
|
||||
|
||||
static void list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_ipporthash *map = set->data;
|
||||
ip_set_ip_t i, *elem;
|
||||
|
||||
for (i = 0; i < map->hashsize; i++) {
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
|
||||
((ip_set_ip_t *)data)[i] = *elem;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ip_set_type ip_set_ipporthash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
.create = &create,
|
||||
.destroy = &destroy,
|
||||
.flush = &flush,
|
||||
.reqsize = sizeof(struct ip_set_req_ipporthash),
|
||||
.addip = &addip,
|
||||
.addip_kernel = &addip_kernel,
|
||||
.retry = &retry,
|
||||
.delip = &delip,
|
||||
.delip_kernel = &delip_kernel,
|
||||
.testip = &testip,
|
||||
.testip_kernel = &testip_kernel,
|
||||
.header_size = sizeof(struct ip_set_req_ipporthash_create),
|
||||
.list_header = &list_header,
|
||||
.list_members_size = &list_members_size,
|
||||
.list_members = &list_members,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
IP_SET_RTYPE(ipporthash, IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
@@ -559,17 +198,4 @@ MODULE_DESCRIPTION("ipporthash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
static int __init ip_set_ipporthash_init(void)
|
||||
{
|
||||
init_max_page_size();
|
||||
return ip_set_register_set_type(&ip_set_ipporthash);
|
||||
}
|
||||
|
||||
static void __exit ip_set_ipporthash_fini(void)
|
||||
{
|
||||
/* FIXME: possible race with ip_set_create() */
|
||||
ip_set_unregister_set_type(&ip_set_ipporthash);
|
||||
}
|
||||
|
||||
module_init(ip_set_ipporthash_init);
|
||||
module_exit(ip_set_ipporthash_fini);
|
||||
REGISTER_MODULE(ipporthash)
|
||||
|
@@ -2,10 +2,9 @@
|
||||
#define __IP_SET_IPPORTHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "ipporthash"
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
#define INVALID_PORT (MAX_RANGE + 1)
|
||||
|
||||
struct ip_set_ipporthash {
|
||||
ip_set_ip_t *members; /* the ipporthash proper */
|
||||
@@ -15,7 +14,7 @@ struct ip_set_ipporthash {
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
void *initval[0]; /* initvals for jhash_1word */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipporthash_create {
|
||||
|
214
extensions/ipset/ip_set_ipportiphash.c
Normal file
214
extensions/ipset/ip_set_ipportiphash.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/* Copyright (C) 2008 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 implementing an ip+port+ip hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_ipportiphash.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
#define jhash_ip2(map, i, ipport, ip1) \
|
||||
jhash_2words(ipport, ip1, *(map->initval + i))
|
||||
|
||||
static inline __u32
|
||||
ipportiphash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
|
||||
if (!(*hash_ip || ip1))
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
if (elem->ip == *hash_ip && elem->ip1 == ip1)
|
||||
return id;
|
||||
/* No shortcut at testing - there can be deleted
|
||||
* entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportiphash_test(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipportiphash_id(set, hash_ip, ip, port, ip1) != UINT_MAX);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
ip_set_ip_t port, ip1; \
|
||||
\
|
||||
if (flags[index+2] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, flags[index+1]); \
|
||||
ip1 = ipaddr(skb, flags[index+2]); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(ipportiphash, test, req->port, req->ip1)
|
||||
KADT(ipportiphash, test, ipaddr, port, ip1)
|
||||
|
||||
static inline int
|
||||
__ipportip_add(struct ip_set_ipportiphash *map,
|
||||
ip_set_ip_t hash_ip, ip_set_ip_t ip1)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
|
||||
if (elem->ip == hash_ip && elem->ip1 == ip1)
|
||||
return -EEXIST;
|
||||
if (!(elem->ip || elem->ip1)) {
|
||||
elem->ip = hash_ip;
|
||||
elem->ip1 = ip1;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
__ipportiphash_add(struct ip_set_ipportiphash *map,
|
||||
struct ipportip *elem)
|
||||
{
|
||||
return __ipportip_add(map, elem->ip, elem->ip1);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportiphash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
|
||||
if (map->elements > limit)
|
||||
return -ERANGE;
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
if (!(*hash_ip || ip1))
|
||||
return -ERANGE;
|
||||
|
||||
return __ipportip_add(map, *hash_ip, ip1);
|
||||
}
|
||||
|
||||
UADT(ipportiphash, add, req->port, req->ip1)
|
||||
KADT(ipportiphash, add, ipaddr, port, ip1)
|
||||
|
||||
static inline void
|
||||
__ipportiphash_retry(struct ip_set_ipportiphash *tmp,
|
||||
struct ip_set_ipportiphash *map)
|
||||
{
|
||||
tmp->first_ip = map->first_ip;
|
||||
tmp->last_ip = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_RETRY2(ipportiphash, struct ipportip)
|
||||
|
||||
static inline int
|
||||
ipportiphash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
ip_set_ip_t id;
|
||||
struct ipportip *elem;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
id = ipportiphash_id(set, hash_ip, ip, port, ip1);
|
||||
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
elem->ip = elem->ip1 = 0;
|
||||
map->elements--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipportiphash, del, req->port, req->ip1)
|
||||
KADT(ipportiphash, del, ipaddr, port, ip1)
|
||||
|
||||
static inline int
|
||||
__ipportiphash_create(const struct ip_set_req_ipportiphash_create *req,
|
||||
struct ip_set_ipportiphash *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(ipportiphash, struct ipportip)
|
||||
HASH_DESTROY(ipportiphash)
|
||||
HASH_FLUSH(ipportiphash, struct ipportip)
|
||||
|
||||
static inline void
|
||||
__ipportiphash_list_header(const struct ip_set_ipportiphash *map,
|
||||
struct ip_set_req_ipportiphash_create *header)
|
||||
{
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(ipportiphash)
|
||||
HASH_LIST_MEMBERS_SIZE(ipportiphash, struct ipportip)
|
||||
HASH_LIST_MEMBERS_MEMCPY(ipportiphash, struct ipportip)
|
||||
|
||||
IP_SET_RTYPE(ipportiphash, IPSET_TYPE_IP | IPSET_TYPE_PORT
|
||||
| IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipportiphash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(ipportiphash)
|
39
extensions/ipset/ip_set_ipportiphash.h
Normal file
39
extensions/ipset/ip_set_ipportiphash.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef __IP_SET_IPPORTIPHASH_H
|
||||
#define __IP_SET_IPPORTIPHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "ipportiphash"
|
||||
|
||||
struct ipportip {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t ip1;
|
||||
};
|
||||
|
||||
struct ip_set_ipportiphash {
|
||||
struct ipportip *members; /* the ipportip proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportiphash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportiphash {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t port;
|
||||
ip_set_ip_t ip1;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPPORTIPHASH_H */
|
302
extensions/ipset/ip_set_ipportnethash.c
Normal file
302
extensions/ipset/ip_set_ipportnethash.c
Normal file
@@ -0,0 +1,302 @@
|
||||
/* Copyright (C) 2008 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 implementing an ip+port+net hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_ipportnethash.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
#define jhash_ip2(map, i, ipport, ip1) \
|
||||
jhash_2words(ipport, ip1, *(map->initval + i))
|
||||
|
||||
static inline __u32
|
||||
ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
|
||||
ip1 = pack_ip_cidr(ip1, cidr);
|
||||
if (!(*hash_ip || ip1))
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
if (elem->ip == *hash_ip && elem->ip1 == ip1)
|
||||
return id;
|
||||
/* No shortcut at testing - there can be deleted
|
||||
* entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline __u32
|
||||
ipportnethash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
__u32 id = UINT_MAX;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && map->cidr[i]; i++) {
|
||||
id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1,
|
||||
map->cidr[i]);
|
||||
if (id != UINT_MAX)
|
||||
break;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportnethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipportnethash_id_cidr(set, hash_ip, ip, port, ip1,
|
||||
cidr) != UINT_MAX);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportnethash_test(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipportnethash_id(set, hash_ip, ip, port, ip1) != UINT_MAX);
|
||||
}
|
||||
|
||||
static int
|
||||
ipportnethash_utest(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_ipportnethash *req = data;
|
||||
|
||||
if (req->cidr <= 0 || req->cidr > 32)
|
||||
return -EINVAL;
|
||||
return (req->cidr == 32
|
||||
? ipportnethash_test(set, hash_ip, req->ip, req->port,
|
||||
req->ip1)
|
||||
: ipportnethash_test_cidr(set, hash_ip, req->ip, req->port,
|
||||
req->ip1, req->cidr));
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
ip_set_ip_t port, ip1; \
|
||||
\
|
||||
if (flags[index+2] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, flags[index+1]); \
|
||||
ip1 = ipaddr(skb, flags[index+2]); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
KADT(ipportnethash, test, ipaddr, port, ip1)
|
||||
|
||||
static inline int
|
||||
__ipportnet_add(struct ip_set_ipportnethash *map,
|
||||
ip_set_ip_t hash_ip, ip_set_ip_t ip1)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
|
||||
if (elem->ip == hash_ip && elem->ip1 == ip1)
|
||||
return -EEXIST;
|
||||
if (!(elem->ip || elem->ip1)) {
|
||||
elem->ip = hash_ip;
|
||||
elem->ip1 = ip1;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
__ipportnethash_add(struct ip_set_ipportnethash *map,
|
||||
struct ipportip *elem)
|
||||
{
|
||||
return __ipportnet_add(map, elem->ip, elem->ip1);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportnethash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
struct ipportip;
|
||||
int ret;
|
||||
|
||||
if (map->elements > limit)
|
||||
return -ERANGE;
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
if (map->nets[cidr-1] == UINT16_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
ip1 = pack_ip_cidr(ip1, cidr);
|
||||
if (!(*hash_ip || ip1))
|
||||
return -ERANGE;
|
||||
|
||||
ret =__ipportnet_add(map, *hash_ip, ip1);
|
||||
if (ret == 0) {
|
||||
if (!map->nets[cidr-1]++)
|
||||
add_cidr_size(map->cidr, cidr);
|
||||
map->elements++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef KADT_CONDITION
|
||||
#define KADT_CONDITION \
|
||||
struct ip_set_ipportnethash *map = set->data; \
|
||||
uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31; \
|
||||
ip_set_ip_t port, ip1; \
|
||||
\
|
||||
if (flags[index+2] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, flags[index+1]); \
|
||||
ip1 = ipaddr(skb, flags[index+2]); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(ipportnethash, add, req->port, req->ip1, req->cidr)
|
||||
KADT(ipportnethash, add, ipaddr, port, ip1, cidr)
|
||||
|
||||
static inline void
|
||||
__ipportnethash_retry(struct ip_set_ipportnethash *tmp,
|
||||
struct ip_set_ipportnethash *map)
|
||||
{
|
||||
tmp->first_ip = map->first_ip;
|
||||
tmp->last_ip = map->last_ip;
|
||||
memcpy(tmp->cidr, map->cidr, sizeof(tmp->cidr));
|
||||
memcpy(tmp->nets, map->nets, sizeof(tmp->nets));
|
||||
}
|
||||
|
||||
HASH_RETRY2(ipportnethash, struct ipportip)
|
||||
|
||||
static inline int
|
||||
ipportnethash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
ip_set_ip_t id;
|
||||
struct ipportip *elem;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
|
||||
id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, cidr);
|
||||
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
elem->ip = elem->ip1 = 0;
|
||||
map->elements--;
|
||||
if (!map->nets[cidr-1]--)
|
||||
del_cidr_size(map->cidr, cidr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipportnethash, del, req->port, req->ip1, req->cidr)
|
||||
KADT(ipportnethash, del, ipaddr, port, ip1, cidr)
|
||||
|
||||
static inline int
|
||||
__ipportnethash_create(const struct ip_set_req_ipportnethash_create *req,
|
||||
struct ip_set_ipportnethash *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
memset(map->cidr, 0, sizeof(map->cidr));
|
||||
memset(map->nets, 0, sizeof(map->nets));
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(ipportnethash, struct ipportip)
|
||||
HASH_DESTROY(ipportnethash)
|
||||
HASH_FLUSH_CIDR(ipportnethash, struct ipportip);
|
||||
|
||||
static inline void
|
||||
__ipportnethash_list_header(const struct ip_set_ipportnethash *map,
|
||||
struct ip_set_req_ipportnethash_create *header)
|
||||
{
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(ipportnethash)
|
||||
|
||||
HASH_LIST_MEMBERS_SIZE(ipportnethash, struct ipportip)
|
||||
HASH_LIST_MEMBERS_MEMCPY(ipportnethash, struct ipportip)
|
||||
|
||||
IP_SET_RTYPE(ipportnethash, IPSET_TYPE_IP | IPSET_TYPE_PORT
|
||||
| IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipportnethash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(ipportnethash)
|
42
extensions/ipset/ip_set_ipportnethash.h
Normal file
42
extensions/ipset/ip_set_ipportnethash.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef __IP_SET_IPPORTNETHASH_H
|
||||
#define __IP_SET_IPPORTNETHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "ipportnethash"
|
||||
|
||||
struct ipportip {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t ip1;
|
||||
};
|
||||
|
||||
struct ip_set_ipportnethash {
|
||||
struct ipportip *members; /* the ipportip proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
uint8_t cidr[30]; /* CIDR sizes */
|
||||
uint16_t nets[30]; /* nr of nets by CIDR sizes */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportnethash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportnethash {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t port;
|
||||
ip_set_ip_t ip1;
|
||||
uint8_t cidr;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPPORTNETHASH_H */
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2005 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
/* Copyright (C) 2005-2008 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
|
||||
@@ -7,24 +7,20 @@
|
||||
|
||||
/* Kernel module implementing an IP set type: the iptree type */
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include "ip_set.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
/* Backward compatibility */
|
||||
#ifndef __nocast
|
||||
#define __nocast
|
||||
#endif
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
#include "ip_set_iptree.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
@@ -35,13 +31,9 @@ static int limit = MAX_RANGE;
|
||||
* to delete the gc timer at destroying/flushing a set */
|
||||
#define IPTREE_DESTROY_SLEEP 100
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
|
||||
static struct kmem_cache *branch_cachep;
|
||||
static struct kmem_cache *leaf_cachep;
|
||||
#else
|
||||
static kmem_cache_t *branch_cachep;
|
||||
static kmem_cache_t *leaf_cachep;
|
||||
#endif
|
||||
static __KMEM_CACHE_T__ *branch_cachep;
|
||||
static __KMEM_CACHE_T__ *leaf_cachep;
|
||||
|
||||
|
||||
#if defined(__LITTLE_ENDIAN)
|
||||
#define ABCD(a,b,c,d,addrp) do { \
|
||||
@@ -69,7 +61,7 @@ static kmem_cache_t *leaf_cachep;
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
iptree_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
@@ -92,52 +84,10 @@ __testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
|| time_after(dtree->expires[d], jiffies));
|
||||
}
|
||||
|
||||
static int
|
||||
testip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_iptree *req = data;
|
||||
#define KADT_CONDITION
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iptree)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_iptree),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __testip(set, req->ip, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
testip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
int res;
|
||||
|
||||
DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
|
||||
flags[index] & IPSET_SRC ? "SRC" : "DST",
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
NIPQUAD(ip_hdr(skb)->saddr),
|
||||
NIPQUAD(ip_hdr(skb)->daddr));
|
||||
#else
|
||||
NIPQUAD(skb->nh.iph->saddr),
|
||||
NIPQUAD(skb->nh.iph->daddr));
|
||||
#endif
|
||||
|
||||
res = __testip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
return (res < 0 ? 0 : res);
|
||||
}
|
||||
UADT(iptree, test)
|
||||
KADT(iptree, test, ipaddr)
|
||||
|
||||
#define ADDIP_WALK(map, elem, branch, type, cachep) do { \
|
||||
if ((map)->tree[elem]) { \
|
||||
@@ -155,8 +105,8 @@ testip_kernel(struct ip_set *set,
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
__addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
|
||||
ip_set_ip_t *hash_ip)
|
||||
iptree_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, unsigned int timeout)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
@@ -179,6 +129,8 @@ __addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
|
||||
if (dtree->expires[d]
|
||||
&& (!map->timeout || time_after(dtree->expires[d], jiffies)))
|
||||
ret = -EEXIST;
|
||||
if (map->timeout && timeout == 0)
|
||||
timeout = map->timeout;
|
||||
dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
|
||||
/* Lottery: I won! */
|
||||
if (dtree->expires[d] == 0)
|
||||
@@ -189,46 +141,8 @@ __addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
addip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
const struct ip_set_req_iptree *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iptree)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_iptree),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
|
||||
return __addip(set, req->ip,
|
||||
req->timeout ? req->timeout : map->timeout,
|
||||
hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
addip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
|
||||
return __addip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
map->timeout,
|
||||
hash_ip);
|
||||
}
|
||||
UADT(iptree, add, req->timeout)
|
||||
KADT(iptree, add, ipaddr, 0)
|
||||
|
||||
#define DELIP_WALK(map, elem, branch) do { \
|
||||
if ((map)->tree[elem]) { \
|
||||
@@ -238,7 +152,7 @@ addip_kernel(struct ip_set *set,
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
iptree_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
@@ -263,39 +177,8 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
static int
|
||||
delip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_iptree *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iptree)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_iptree),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __delip(set, req->ip, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
delip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
return __delip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
}
|
||||
UADT(iptree, del)
|
||||
KADT(iptree, del, ipaddr)
|
||||
|
||||
#define LOOP_WALK_BEGIN(map, i, branch) \
|
||||
for (i = 0; i < 256; i++) { \
|
||||
@@ -305,7 +188,8 @@ delip_kernel(struct ip_set *set,
|
||||
|
||||
#define LOOP_WALK_END }
|
||||
|
||||
static void ip_tree_gc(unsigned long ul_set)
|
||||
static void
|
||||
ip_tree_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct ip_set_iptree *map = set->data;
|
||||
@@ -375,7 +259,8 @@ static void ip_tree_gc(unsigned long ul_set)
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static inline void init_gc_timer(struct ip_set *set)
|
||||
static inline void
|
||||
init_gc_timer(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
|
||||
@@ -390,7 +275,8 @@ static inline void init_gc_timer(struct ip_set *set)
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static int create(struct ip_set *set, const void *data, size_t size)
|
||||
static int
|
||||
iptree_create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
const struct ip_set_req_iptree_create *req = data;
|
||||
struct ip_set_iptree *map;
|
||||
@@ -418,7 +304,8 @@ static int create(struct ip_set *set, const void *data, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __flush(struct ip_set_iptree *map)
|
||||
static inline void
|
||||
__flush(struct ip_set_iptree *map)
|
||||
{
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
@@ -437,7 +324,8 @@ static void __flush(struct ip_set_iptree *map)
|
||||
map->elements = 0;
|
||||
}
|
||||
|
||||
static void destroy(struct ip_set *set)
|
||||
static void
|
||||
iptree_destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
|
||||
@@ -449,7 +337,8 @@ static void destroy(struct ip_set *set)
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void flush(struct ip_set *set)
|
||||
static void
|
||||
iptree_flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
unsigned int timeout = map->timeout;
|
||||
@@ -464,7 +353,8 @@ static void flush(struct ip_set *set)
|
||||
init_gc_timer(set);
|
||||
}
|
||||
|
||||
static void list_header(const struct ip_set *set, void *data)
|
||||
static void
|
||||
iptree_list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_req_iptree_create *header = data;
|
||||
@@ -472,7 +362,8 @@ static void list_header(const struct ip_set *set, void *data)
|
||||
header->timeout = map->timeout;
|
||||
}
|
||||
|
||||
static int list_members_size(const struct ip_set *set)
|
||||
static int
|
||||
iptree_list_members_size(const struct ip_set *set)
|
||||
{
|
||||
const struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
@@ -497,7 +388,8 @@ static int list_members_size(const struct ip_set *set)
|
||||
return (count * sizeof(struct ip_set_req_iptree));
|
||||
}
|
||||
|
||||
static void list_members(const struct ip_set *set, void *data)
|
||||
static void
|
||||
iptree_list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
@@ -525,26 +417,7 @@ static void list_members(const struct ip_set *set, void *data)
|
||||
LOOP_WALK_END;
|
||||
}
|
||||
|
||||
static struct ip_set_type ip_set_iptree = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
.create = &create,
|
||||
.destroy = &destroy,
|
||||
.flush = &flush,
|
||||
.reqsize = sizeof(struct ip_set_req_iptree),
|
||||
.addip = &addip,
|
||||
.addip_kernel = &addip_kernel,
|
||||
.delip = &delip,
|
||||
.delip_kernel = &delip_kernel,
|
||||
.testip = &testip,
|
||||
.testip_kernel = &testip_kernel,
|
||||
.header_size = sizeof(struct ip_set_req_iptree_create),
|
||||
.list_header = &list_header,
|
||||
.list_members_size = &list_members_size,
|
||||
.list_members = &list_members,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
IP_SET_TYPE(iptree, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
@@ -556,29 +429,15 @@ static int __init ip_set_iptree_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
|
||||
branch_cachep = kmem_cache_create("ip_set_iptreeb",
|
||||
sizeof(struct ip_set_iptreeb),
|
||||
0, 0, NULL);
|
||||
#else
|
||||
branch_cachep = kmem_cache_create("ip_set_iptreeb",
|
||||
sizeof(struct ip_set_iptreeb),
|
||||
0, 0, NULL, NULL);
|
||||
#endif
|
||||
branch_cachep = KMEM_CACHE_CREATE("ip_set_iptreeb",
|
||||
sizeof(struct ip_set_iptreeb));
|
||||
if (!branch_cachep) {
|
||||
printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
|
||||
leaf_cachep = kmem_cache_create("ip_set_iptreed",
|
||||
sizeof(struct ip_set_iptreed),
|
||||
0, 0, NULL);
|
||||
#else
|
||||
leaf_cachep = kmem_cache_create("ip_set_iptreed",
|
||||
sizeof(struct ip_set_iptreed),
|
||||
0, 0, NULL, NULL);
|
||||
#endif
|
||||
leaf_cachep = KMEM_CACHE_CREATE("ip_set_iptreed",
|
||||
sizeof(struct ip_set_iptreed));
|
||||
if (!leaf_cachep) {
|
||||
printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n");
|
||||
ret = -ENOMEM;
|
||||
|
@@ -4,7 +4,6 @@
|
||||
#include "ip_set.h"
|
||||
|
||||
#define SETTYPE_NAME "iptree"
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
|
||||
struct ip_set_iptreed {
|
||||
unsigned long expires[256]; /* x.x.x.ADDR */
|
||||
|
@@ -11,34 +11,28 @@
|
||||
* index to find the bitmap and the last octet is used as the bit number.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include "ip_set.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
#include "ip_set_iptreemap.h"
|
||||
|
||||
#define IPTREEMAP_DEFAULT_GC_TIME (5 * 60)
|
||||
#define IPTREEMAP_DESTROY_SLEEP (100)
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
|
||||
static struct kmem_cache *cachep_b;
|
||||
static struct kmem_cache *cachep_c;
|
||||
static struct kmem_cache *cachep_d;
|
||||
#else
|
||||
static kmem_cache_t *cachep_b;
|
||||
static kmem_cache_t *cachep_c;
|
||||
static kmem_cache_t *cachep_d;
|
||||
#endif
|
||||
static __KMEM_CACHE_T__ *cachep_b;
|
||||
static __KMEM_CACHE_T__ *cachep_c;
|
||||
static __KMEM_CACHE_T__ *cachep_d;
|
||||
|
||||
static struct ip_set_iptreemap_d *fullbitmap_d;
|
||||
static struct ip_set_iptreemap_c *fullbitmap_c;
|
||||
@@ -256,7 +250,7 @@ free_b(struct ip_set_iptreemap_b *map)
|
||||
}
|
||||
|
||||
static inline int
|
||||
__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
iptreemap_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
@@ -275,40 +269,13 @@ __testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
return !!test_bit(d, (void *) dtree->bitmap);
|
||||
}
|
||||
|
||||
static int
|
||||
testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_iptreemap *req = data;
|
||||
#define KADT_CONDITION
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iptreemap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return __testip(set, req->start, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
testip_kernel(struct ip_set *set, const struct sk_buff *skb, ip_set_ip_t *hash_ip, const u_int32_t *flags, unsigned char index)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = __testip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
|
||||
return (res < 0 ? 0 : res);
|
||||
}
|
||||
UADT(iptreemap, test)
|
||||
KADT(iptreemap, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__addip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
__addip_single(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
@@ -333,7 +300,8 @@ __addip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
}
|
||||
|
||||
static inline int
|
||||
__addip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip)
|
||||
iptreemap_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t start, ip_set_ip_t end)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
@@ -344,7 +312,7 @@ __addip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_
|
||||
unsigned char a2, b2, c2, d2;
|
||||
|
||||
if (start == end)
|
||||
return __addip_single(set, start, hash_ip);
|
||||
return __addip_single(set, hash_ip, start);
|
||||
|
||||
*hash_ip = start;
|
||||
|
||||
@@ -365,37 +333,12 @@ __addip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
addip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_iptreemap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iptreemap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return __addip_range(set, min(req->start, req->end), max(req->start, req->end), hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
addip_kernel(struct ip_set *set, const struct sk_buff *skb, ip_set_ip_t *hash_ip, const u_int32_t *flags, unsigned char index)
|
||||
{
|
||||
|
||||
return __addip_single(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
}
|
||||
UADT0(iptreemap, add, min(req->ip, req->end), max(req->ip, req->end))
|
||||
KADT(iptreemap, add, ipaddr, ip)
|
||||
|
||||
static inline int
|
||||
__delip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
|
||||
__delip_single(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, unsigned int __nocast flags)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
@@ -420,7 +363,8 @@ __delip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip, unsigne
|
||||
}
|
||||
|
||||
static inline int
|
||||
__delip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
|
||||
iptreemap_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t start, ip_set_ip_t end, unsigned int __nocast flags)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
@@ -431,7 +375,7 @@ __delip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_
|
||||
unsigned char a2, b2, c2, d2;
|
||||
|
||||
if (start == end)
|
||||
return __delip_single(set, start, hash_ip, flags);
|
||||
return __delip_single(set, hash_ip, start, flags);
|
||||
|
||||
*hash_ip = start;
|
||||
|
||||
@@ -452,34 +396,8 @@ __delip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
delip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_iptreemap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iptreemap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return __delip_range(set, min(req->start, req->end), max(req->start, req->end), hash_ip, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static int
|
||||
delip_kernel(struct ip_set *set, const struct sk_buff *skb, ip_set_ip_t *hash_ip, const u_int32_t *flags, unsigned char index)
|
||||
{
|
||||
return __delip_single(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip,
|
||||
GFP_ATOMIC);
|
||||
}
|
||||
UADT0(iptreemap, del, min(req->ip, req->end), max(req->ip, req->end), GFP_KERNEL)
|
||||
KADT(iptreemap, del, ipaddr, ip, GFP_ATOMIC)
|
||||
|
||||
/* Check the status of the bitmap
|
||||
* -1 == all bits cleared
|
||||
@@ -551,16 +469,12 @@ init_gc_timer(struct ip_set *set)
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static int create(struct ip_set *set, const void *data, size_t size)
|
||||
static int
|
||||
iptreemap_create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
const struct ip_set_req_iptreemap_create *req = data;
|
||||
struct ip_set_iptreemap *map;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iptreemap_create)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap_create), size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
@@ -573,7 +487,8 @@ static int create(struct ip_set *set, const void *data, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void __flush(struct ip_set_iptreemap *map)
|
||||
static inline void
|
||||
__flush(struct ip_set_iptreemap *map)
|
||||
{
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
unsigned int a;
|
||||
@@ -584,7 +499,8 @@ static inline void __flush(struct ip_set_iptreemap *map)
|
||||
LOOP_WALK_END();
|
||||
}
|
||||
|
||||
static void destroy(struct ip_set *set)
|
||||
static void
|
||||
iptreemap_destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
|
||||
@@ -597,7 +513,8 @@ static void destroy(struct ip_set *set)
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void flush(struct ip_set *set)
|
||||
static void
|
||||
iptreemap_flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
|
||||
@@ -611,7 +528,8 @@ static void flush(struct ip_set *set)
|
||||
init_gc_timer(set);
|
||||
}
|
||||
|
||||
static void list_header(const struct ip_set *set, void *data)
|
||||
static void
|
||||
iptreemap_list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_req_iptreemap_create *header = data;
|
||||
@@ -619,7 +537,8 @@ static void list_header(const struct ip_set *set, void *data)
|
||||
header->gc_interval = map->gc_interval;
|
||||
}
|
||||
|
||||
static int list_members_size(const struct ip_set *set)
|
||||
static int
|
||||
iptreemap_list_members_size(const struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
@@ -648,17 +567,19 @@ static int list_members_size(const struct ip_set *set)
|
||||
return (count * sizeof(struct ip_set_req_iptreemap));
|
||||
}
|
||||
|
||||
static inline size_t add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end)
|
||||
static inline size_t
|
||||
add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end)
|
||||
{
|
||||
struct ip_set_req_iptreemap *entry = data + offset;
|
||||
|
||||
entry->start = start;
|
||||
entry->ip = start;
|
||||
entry->end = end;
|
||||
|
||||
return sizeof(*entry);
|
||||
}
|
||||
|
||||
static void list_members(const struct ip_set *set, void *data)
|
||||
static void
|
||||
iptreemap_list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
@@ -695,26 +616,7 @@ static void list_members(const struct ip_set *set, void *data)
|
||||
add_member(data, offset, start, end);
|
||||
}
|
||||
|
||||
static struct ip_set_type ip_set_iptreemap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
.create = create,
|
||||
.destroy = destroy,
|
||||
.flush = flush,
|
||||
.reqsize = sizeof(struct ip_set_req_iptreemap),
|
||||
.addip = addip,
|
||||
.addip_kernel = addip_kernel,
|
||||
.delip = delip,
|
||||
.delip_kernel = delip_kernel,
|
||||
.testip = testip,
|
||||
.testip_kernel = testip_kernel,
|
||||
.header_size = sizeof(struct ip_set_req_iptreemap_create),
|
||||
.list_header = list_header,
|
||||
.list_members_size = list_members_size,
|
||||
.list_members = list_members,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
IP_SET_TYPE(iptreemap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Sven Wegener <sven.wegener@stealer.net>");
|
||||
@@ -725,43 +627,22 @@ static int __init ip_set_iptreemap_init(void)
|
||||
int ret = -ENOMEM;
|
||||
int a;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
|
||||
cachep_b = kmem_cache_create("ip_set_iptreemap_b",
|
||||
sizeof(struct ip_set_iptreemap_b),
|
||||
0, 0, NULL);
|
||||
#else
|
||||
cachep_b = kmem_cache_create("ip_set_iptreemap_b",
|
||||
sizeof(struct ip_set_iptreemap_b),
|
||||
0, 0, NULL, NULL);
|
||||
#endif
|
||||
cachep_b = KMEM_CACHE_CREATE("ip_set_iptreemap_b",
|
||||
sizeof(struct ip_set_iptreemap_b));
|
||||
if (!cachep_b) {
|
||||
ip_set_printk("Unable to create ip_set_iptreemap_b slab cache");
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
|
||||
cachep_c = kmem_cache_create("ip_set_iptreemap_c",
|
||||
sizeof(struct ip_set_iptreemap_c),
|
||||
0, 0, NULL);
|
||||
#else
|
||||
cachep_c = kmem_cache_create("ip_set_iptreemap_c",
|
||||
sizeof(struct ip_set_iptreemap_c),
|
||||
0, 0, NULL, NULL);
|
||||
#endif
|
||||
cachep_c = KMEM_CACHE_CREATE("ip_set_iptreemap_c",
|
||||
sizeof(struct ip_set_iptreemap_c));
|
||||
if (!cachep_c) {
|
||||
ip_set_printk("Unable to create ip_set_iptreemap_c slab cache");
|
||||
goto outb;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
|
||||
cachep_d = kmem_cache_create("ip_set_iptreemap_d",
|
||||
sizeof(struct ip_set_iptreemap_d),
|
||||
0, 0, NULL);
|
||||
#else
|
||||
cachep_d = kmem_cache_create("ip_set_iptreemap_d",
|
||||
sizeof(struct ip_set_iptreemap_d),
|
||||
0, 0, NULL, NULL);
|
||||
#endif
|
||||
cachep_d = KMEM_CACHE_CREATE("ip_set_iptreemap_d",
|
||||
sizeof(struct ip_set_iptreemap_d));
|
||||
if (!cachep_d) {
|
||||
ip_set_printk("Unable to create ip_set_iptreemap_d slab cache");
|
||||
goto outc;
|
||||
|
@@ -33,7 +33,7 @@ struct ip_set_req_iptreemap_create {
|
||||
};
|
||||
|
||||
struct ip_set_req_iptreemap {
|
||||
ip_set_ip_t start;
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t end;
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* 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>
|
||||
* Copyright (C) 2003-2008 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
|
||||
@@ -13,33 +13,22 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include "ip_set.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include "ip_set_malloc.h"
|
||||
#include "ip_set_macipmap.h"
|
||||
|
||||
static int
|
||||
testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
|
||||
macipmap_utest(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
struct ip_set_macip *table = map->members;
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
const struct ip_set_macip *table = map->members;
|
||||
const struct ip_set_req_macipmap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_macipmap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_macipmap),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (req->ip < map->first_ip || req->ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
@@ -57,24 +46,17 @@ testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
|
||||
}
|
||||
|
||||
static int
|
||||
testip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
macipmap_ktest(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
struct ip_set_macip *table = map->members;
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
const struct ip_set_macip *table = map->members;
|
||||
ip_set_ip_t ip;
|
||||
|
||||
ip = ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr);
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr);
|
||||
#endif
|
||||
ip = ipaddr(skb, flags[index]);
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return 0;
|
||||
@@ -86,13 +68,8 @@ testip_kernel(struct ip_set *set,
|
||||
(void *) &table[ip - map->first_ip].flags)) {
|
||||
/* Is mac pointer valid?
|
||||
* If so, compare... */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
return (skb_mac_header(skb) >= skb->head
|
||||
&& (skb_mac_header(skb) + ETH_HLEN) <= skb->data
|
||||
#else
|
||||
return (skb->mac.raw >= skb->head
|
||||
&& (skb->mac.raw + ETH_HLEN) <= skb->data
|
||||
#endif
|
||||
&& (memcmp(eth_hdr(skb)->h_source,
|
||||
&table[ip - map->first_ip].ethernet,
|
||||
ETH_ALEN) == 0));
|
||||
@@ -103,8 +80,8 @@ testip_kernel(struct ip_set *set,
|
||||
|
||||
/* returns 0 on success */
|
||||
static inline int
|
||||
__addip(struct ip_set *set,
|
||||
ip_set_ip_t ip, const unsigned char *ethernet, ip_set_ip_t *hash_ip)
|
||||
macipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, const unsigned char *ethernet)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
struct ip_set_macip *table = map->members;
|
||||
@@ -121,53 +98,16 @@ __addip(struct ip_set *set,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
addip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_macipmap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_macipmap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_macipmap),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __addip(set, req->ip, req->ethernet, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
addip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
ip_set_ip_t ip;
|
||||
|
||||
ip = ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr);
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
if (!(skb_mac_header(skb) >= skb->head
|
||||
&& (skb_mac_header(skb) + ETH_HLEN) <= skb->data))
|
||||
#else
|
||||
if (!(skb->mac.raw >= skb->head
|
||||
&& (skb->mac.raw + ETH_HLEN) <= skb->data))
|
||||
#endif
|
||||
#define KADT_CONDITION \
|
||||
if (!(skb_mac_header(skb) >= skb->head \
|
||||
&& (skb_mac_header(skb) + ETH_HLEN) <= skb->data))\
|
||||
return -EINVAL;
|
||||
|
||||
return __addip(set, ip, eth_hdr(skb)->h_source, hash_ip);
|
||||
}
|
||||
UADT(macipmap, add, req->ethernet)
|
||||
KADT(macipmap, add, ipaddr, eth_hdr(skb)->h_source)
|
||||
|
||||
static inline int
|
||||
__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
macipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
struct ip_set_macip *table = map->members;
|
||||
@@ -183,178 +123,44 @@ __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
delip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
#undef KADT_CONDITION
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(macipmap, del)
|
||||
KADT(macipmap, del, ipaddr)
|
||||
|
||||
static inline int
|
||||
__macipmap_create(const struct ip_set_req_macipmap_create *req,
|
||||
struct ip_set_macipmap *map)
|
||||
{
|
||||
const struct ip_set_req_macipmap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_macipmap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_macipmap),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __delip(set, req->ip, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
delip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
return __delip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
}
|
||||
|
||||
static inline size_t members_size(ip_set_ip_t from, ip_set_ip_t to)
|
||||
{
|
||||
return (size_t)((to - from + 1) * sizeof(struct ip_set_macip));
|
||||
}
|
||||
|
||||
static int create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
size_t newbytes;
|
||||
const struct ip_set_req_macipmap_create *req = data;
|
||||
struct ip_set_macipmap *map;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_macipmap_create)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_macipmap_create),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DP("from %u.%u.%u.%u to %u.%u.%u.%u",
|
||||
HIPQUAD(req->from), HIPQUAD(req->to));
|
||||
|
||||
if (req->from > req->to) {
|
||||
DP("bad ip range");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big (max %d addresses)",
|
||||
MAX_RANGE+1);
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
|
||||
if (!map) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_macipmap));
|
||||
return -ENOMEM;
|
||||
}
|
||||
map->flags = req->flags;
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
newbytes = members_size(map->first_ip, map->last_ip);
|
||||
map->members = ip_set_malloc(newbytes);
|
||||
DP("members: %u %p", newbytes, map->members);
|
||||
if (!map->members) {
|
||||
DP("out of memory for %d bytes", newbytes);
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(map->members, 0, newbytes);
|
||||
|
||||
set->data = map;
|
||||
return 0;
|
||||
return (req->to - req->from + 1) * sizeof(struct ip_set_macip);
|
||||
}
|
||||
|
||||
static void destroy(struct ip_set *set)
|
||||
BITMAP_CREATE(macipmap)
|
||||
BITMAP_DESTROY(macipmap)
|
||||
BITMAP_FLUSH(macipmap)
|
||||
|
||||
static inline void
|
||||
__macipmap_list_header(const struct ip_set_macipmap *map,
|
||||
struct ip_set_req_macipmap_create *header)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
|
||||
ip_set_free(map->members, members_size(map->first_ip, map->last_ip));
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
memset(map->members, 0, members_size(map->first_ip, map->last_ip));
|
||||
}
|
||||
|
||||
static void list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
struct ip_set_req_macipmap_create *header = data;
|
||||
|
||||
DP("list_header %x %x %u", map->first_ip, map->last_ip,
|
||||
map->flags);
|
||||
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
header->flags = map->flags;
|
||||
}
|
||||
|
||||
static int list_members_size(const struct ip_set *set)
|
||||
{
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
BITMAP_LIST_HEADER(macipmap)
|
||||
BITMAP_LIST_MEMBERS_SIZE(macipmap)
|
||||
BITMAP_LIST_MEMBERS(macipmap)
|
||||
|
||||
DP("%u", members_size(map->first_ip, map->last_ip));
|
||||
return members_size(map->first_ip, map->last_ip);
|
||||
}
|
||||
|
||||
static void list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
|
||||
int bytes = members_size(map->first_ip, map->last_ip);
|
||||
|
||||
DP("members: %u %p", bytes, map->members);
|
||||
memcpy(data, map->members, bytes);
|
||||
}
|
||||
|
||||
static struct ip_set_type ip_set_macipmap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
.create = &create,
|
||||
.destroy = &destroy,
|
||||
.flush = &flush,
|
||||
.reqsize = sizeof(struct ip_set_req_macipmap),
|
||||
.addip = &addip,
|
||||
.addip_kernel = &addip_kernel,
|
||||
.delip = &delip,
|
||||
.delip_kernel = &delip_kernel,
|
||||
.testip = &testip,
|
||||
.testip_kernel = &testip_kernel,
|
||||
.header_size = sizeof(struct ip_set_req_macipmap_create),
|
||||
.list_header = &list_header,
|
||||
.list_members_size = &list_members_size,
|
||||
.list_members = &list_members,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
IP_SET_TYPE(macipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("macipmap type of IP sets");
|
||||
|
||||
static int __init ip_set_macipmap_init(void)
|
||||
{
|
||||
init_max_page_size();
|
||||
return ip_set_register_set_type(&ip_set_macipmap);
|
||||
}
|
||||
|
||||
static void __exit ip_set_macipmap_fini(void)
|
||||
{
|
||||
/* FIXME: possible race with ip_set_create() */
|
||||
ip_set_unregister_set_type(&ip_set_macipmap);
|
||||
}
|
||||
|
||||
module_init(ip_set_macipmap_init);
|
||||
module_exit(ip_set_macipmap_fini);
|
||||
REGISTER_MODULE(macipmap)
|
||||
|
@@ -2,9 +2,9 @@
|
||||
#define __IP_SET_MACIPMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
|
||||
#define SETTYPE_NAME "macipmap"
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
|
||||
/* general flags */
|
||||
#define IPSET_MACIP_MATCHUNSET 1
|
||||
@@ -17,6 +17,7 @@ struct ip_set_macipmap {
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
u_int32_t flags;
|
||||
size_t size; /* size of the ipmap proper */
|
||||
};
|
||||
|
||||
struct ip_set_req_macipmap_create {
|
||||
|
@@ -2,13 +2,22 @@
|
||||
#define _IP_SET_MALLOC_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
static size_t max_malloc_size = 0, max_page_size = 0;
|
||||
static size_t default_max_malloc_size = 131072; /* Guaranteed: slab.c */
|
||||
|
||||
static inline unsigned int init_max_page_size(void)
|
||||
static inline int init_max_page_size(void)
|
||||
{
|
||||
/* Compatibility glues to support 2.4.36 */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
#define __GFP_NOWARN 0
|
||||
|
||||
/* Guaranteed: slab.c */
|
||||
max_malloc_size = max_page_size = default_max_malloc_size;
|
||||
#else
|
||||
size_t page_size = 0;
|
||||
|
||||
|
||||
#define CACHE(x) if (max_page_size == 0 || x < max_page_size) \
|
||||
page_size = x;
|
||||
#include <linux/kmalloc_sizes.h>
|
||||
@@ -21,6 +30,7 @@ static inline unsigned int init_max_page_size(void)
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -122,7 +132,7 @@ static inline void * ip_set_malloc(size_t bytes)
|
||||
{
|
||||
BUG_ON(max_malloc_size == 0);
|
||||
|
||||
if (bytes > max_malloc_size)
|
||||
if (bytes > default_max_malloc_size)
|
||||
return vmalloc(bytes);
|
||||
else
|
||||
return kmalloc(bytes, GFP_KERNEL | __GFP_NOWARN);
|
||||
@@ -132,7 +142,7 @@ static inline void ip_set_free(void * data, size_t bytes)
|
||||
{
|
||||
BUG_ON(max_malloc_size == 0);
|
||||
|
||||
if (bytes > max_malloc_size)
|
||||
if (bytes > default_max_malloc_size)
|
||||
vfree(data);
|
||||
else
|
||||
kfree(data);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
/* Copyright (C) 2003-2008 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
|
||||
@@ -8,43 +8,35 @@
|
||||
/* Kernel module implementing a cidr nethash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include "ip_set.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_malloc.h"
|
||||
#include "ip_set_nethash.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
static inline __u32
|
||||
jhash_ip(const struct ip_set_nethash *map, uint16_t i, ip_set_ip_t ip)
|
||||
{
|
||||
return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
|
||||
}
|
||||
|
||||
static inline __u32
|
||||
hash_id_cidr(struct ip_set_nethash *map,
|
||||
ip_set_ip_t ip,
|
||||
unsigned char cidr,
|
||||
ip_set_ip_t *hash_ip)
|
||||
nethash_id_cidr(const struct ip_set_nethash *map,
|
||||
ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip,
|
||||
uint8_t cidr)
|
||||
{
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
*hash_ip = pack(ip, cidr);
|
||||
*hash_ip = pack_ip_cidr(ip, cidr);
|
||||
if (!*hash_ip)
|
||||
return MAX_RANGE;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip(map, i, *hash_ip) % map->hashsize;
|
||||
@@ -57,14 +49,14 @@ hash_id_cidr(struct ip_set_nethash *map,
|
||||
}
|
||||
|
||||
static inline __u32
|
||||
hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
nethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
const struct ip_set_nethash *map = set->data;
|
||||
__u32 id = UINT_MAX;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && map->cidr[i]; i++) {
|
||||
id = hash_id_cidr(map, ip, map->cidr[i], hash_ip);
|
||||
id = nethash_id_cidr(map, hash_ip, ip, map->cidr[i]);
|
||||
if (id != UINT_MAX)
|
||||
break;
|
||||
}
|
||||
@@ -72,70 +64,50 @@ hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
}
|
||||
|
||||
static inline int
|
||||
__testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr,
|
||||
ip_set_ip_t *hash_ip)
|
||||
nethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
const struct ip_set_nethash *map = set->data;
|
||||
|
||||
return (ip && hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX);
|
||||
return (nethash_id_cidr(map, hash_ip, ip, cidr) != UINT_MAX);
|
||||
}
|
||||
|
||||
static inline int
|
||||
__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
|
||||
nethash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
return (ip && hash_id(set, ip, hash_ip) != UINT_MAX);
|
||||
return (nethash_id(set, hash_ip, ip) != UINT_MAX);
|
||||
}
|
||||
|
||||
static int
|
||||
testip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
nethash_utest(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_nethash *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_nethash)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_nethash),
|
||||
size);
|
||||
if (req->cidr <= 0 || req->cidr > 32)
|
||||
return -EINVAL;
|
||||
}
|
||||
return (req->cidr == 32 ? __testip(set, req->ip, hash_ip)
|
||||
: __testip_cidr(set, req->ip, req->cidr, hash_ip));
|
||||
return (req->cidr == 32 ? nethash_test(set, hash_ip, req->ip)
|
||||
: nethash_test_cidr(set, hash_ip, req->ip, req->cidr));
|
||||
}
|
||||
|
||||
static int
|
||||
testip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
return __testip(set,
|
||||
ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr),
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr),
|
||||
#endif
|
||||
hash_ip);
|
||||
}
|
||||
#define KADT_CONDITION
|
||||
|
||||
KADT(nethash, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
|
||||
__nethash_add(struct ip_set_nethash *map, ip_set_ip_t *ip)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip(map, i, ip) % map->hashsize;
|
||||
probe = jhash_ip(map, i, *ip) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
|
||||
if (*elem == ip)
|
||||
if (*elem == *ip)
|
||||
return -EEXIST;
|
||||
if (!*elem) {
|
||||
*elem = ip;
|
||||
map->elements++;
|
||||
*elem = *ip;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -144,329 +116,100 @@ __addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
|
||||
}
|
||||
|
||||
static inline int
|
||||
__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
|
||||
ip_set_ip_t *hash_ip)
|
||||
nethash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, uint8_t cidr)
|
||||
{
|
||||
if (!ip || map->elements >= limit)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = pack(ip, cidr);
|
||||
DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
|
||||
|
||||
return __addip_base(map, *hash_ip);
|
||||
}
|
||||
|
||||
static void
|
||||
update_cidr_sizes(struct ip_set_nethash *map, unsigned char cidr)
|
||||
{
|
||||
unsigned char next;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && map->cidr[i]; i++) {
|
||||
if (map->cidr[i] == cidr) {
|
||||
return;
|
||||
} else if (map->cidr[i] < cidr) {
|
||||
next = map->cidr[i];
|
||||
map->cidr[i] = cidr;
|
||||
cidr = next;
|
||||
}
|
||||
}
|
||||
if (i < 30)
|
||||
map->cidr[i] = cidr;
|
||||
}
|
||||
|
||||
static int
|
||||
addip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_nethash *req = data;
|
||||
struct ip_set_nethash *map = set->data;
|
||||
int ret;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_nethash)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_nethash),
|
||||
size);
|
||||
|
||||
if (map->elements >= limit || map->nets[cidr-1] == UINT16_MAX)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = __addip(set->data, req->ip, req->cidr, hash_ip);
|
||||
|
||||
if (ret == 0)
|
||||
update_cidr_sizes(set->data, req->cidr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
addip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
int ret = -ERANGE;
|
||||
ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr);
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr);
|
||||
#endif
|
||||
|
||||
if (map->cidr[0])
|
||||
ret = __addip(map, ip, map->cidr[0], hash_ip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int retry(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
ip_set_ip_t *elem;
|
||||
void *members;
|
||||
u_int32_t i, hashsize = map->hashsize;
|
||||
int res;
|
||||
struct ip_set_nethash *tmp;
|
||||
|
||||
if (map->resize == 0)
|
||||
*hash_ip = pack_ip_cidr(ip, cidr);
|
||||
DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
|
||||
if (!*hash_ip)
|
||||
return -ERANGE;
|
||||
|
||||
again:
|
||||
res = 0;
|
||||
|
||||
/* Calculate new parameters */
|
||||
hashsize += (hashsize * map->resize)/100;
|
||||
if (hashsize == map->hashsize)
|
||||
hashsize++;
|
||||
|
||||
ip_set_printk("rehashing of set %s triggered: "
|
||||
"hashsize grows from %u to %u",
|
||||
set->name, map->hashsize, hashsize);
|
||||
|
||||
tmp = kmalloc(sizeof(struct ip_set_nethash)
|
||||
+ map->probes * sizeof(uint32_t), GFP_ATOMIC);
|
||||
if (!tmp) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_nethash)
|
||||
+ map->probes * sizeof(uint32_t));
|
||||
return -ENOMEM;
|
||||
}
|
||||
tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
|
||||
if (!tmp->members) {
|
||||
DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
|
||||
kfree(tmp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
tmp->hashsize = hashsize;
|
||||
tmp->elements = 0;
|
||||
tmp->probes = map->probes;
|
||||
tmp->resize = map->resize;
|
||||
memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
|
||||
memcpy(tmp->cidr, map->cidr, 30 * sizeof(unsigned char));
|
||||
|
||||
write_lock_bh(&set->lock);
|
||||
map = set->data; /* Play safe */
|
||||
for (i = 0; i < map->hashsize && res == 0; i++) {
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
|
||||
if (*elem)
|
||||
res = __addip_base(tmp, *elem);
|
||||
}
|
||||
if (res) {
|
||||
/* Failure, try again */
|
||||
write_unlock_bh(&set->lock);
|
||||
harray_free(tmp->members);
|
||||
kfree(tmp);
|
||||
goto again;
|
||||
ret = __nethash_add(map, hash_ip);
|
||||
if (ret == 0) {
|
||||
if (!map->nets[cidr-1]++)
|
||||
add_cidr_size(map->cidr, cidr);
|
||||
map->elements++;
|
||||
}
|
||||
|
||||
/* Success at resizing! */
|
||||
members = map->members;
|
||||
|
||||
map->hashsize = tmp->hashsize;
|
||||
map->members = tmp->members;
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
harray_free(members);
|
||||
kfree(tmp);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef KADT_CONDITION
|
||||
#define KADT_CONDITION \
|
||||
struct ip_set_nethash *map = set->data; \
|
||||
uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31;
|
||||
|
||||
UADT(nethash, add, req->cidr)
|
||||
KADT(nethash, add, ipaddr, cidr)
|
||||
|
||||
static inline void
|
||||
__nethash_retry(struct ip_set_nethash *tmp, struct ip_set_nethash *map)
|
||||
{
|
||||
memcpy(tmp->cidr, map->cidr, sizeof(tmp->cidr));
|
||||
memcpy(tmp->nets, map->nets, sizeof(tmp->nets));
|
||||
}
|
||||
|
||||
HASH_RETRY(nethash, ip_set_ip_t)
|
||||
|
||||
static inline int
|
||||
__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
|
||||
ip_set_ip_t *hash_ip)
|
||||
nethash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
ip_set_ip_t id, *elem;
|
||||
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
|
||||
id = hash_id_cidr(map, ip, cidr, hash_ip);
|
||||
id = nethash_id_cidr(map, hash_ip, ip, cidr);
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
*elem = 0;
|
||||
map->elements--;
|
||||
if (!map->nets[cidr-1]--)
|
||||
del_cidr_size(map->cidr, cidr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
delip(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
UADT(nethash, del, req->cidr)
|
||||
KADT(nethash, del, ipaddr, cidr)
|
||||
|
||||
static inline int
|
||||
__nethash_create(const struct ip_set_req_nethash_create *req,
|
||||
struct ip_set_nethash *map)
|
||||
{
|
||||
const struct ip_set_req_nethash *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_nethash)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_nethash),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* TODO: no garbage collection in map->cidr */
|
||||
return __delip(set->data, req->ip, req->cidr, hash_ip);
|
||||
}
|
||||
|
||||
static int
|
||||
delip_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
int ret = -ERANGE;
|
||||
ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
? ip_hdr(skb)->saddr
|
||||
: ip_hdr(skb)->daddr);
|
||||
#else
|
||||
? skb->nh.iph->saddr
|
||||
: skb->nh.iph->daddr);
|
||||
#endif
|
||||
memset(map->cidr, 0, sizeof(map->cidr));
|
||||
memset(map->nets, 0, sizeof(map->nets));
|
||||
|
||||
if (map->cidr[0])
|
||||
ret = __delip(map, ip, map->cidr[0], hash_ip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
const struct ip_set_req_nethash_create *req = data;
|
||||
struct ip_set_nethash *map;
|
||||
uint16_t i;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_nethash_create)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_nethash_create),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (req->hashsize < 1) {
|
||||
ip_set_printk("hashsize too small");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
if (req->probes < 1) {
|
||||
ip_set_printk("probes too small");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_nethash)
|
||||
+ req->probes * sizeof(uint32_t), GFP_KERNEL);
|
||||
if (!map) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_nethash)
|
||||
+ req->probes * sizeof(uint32_t));
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (i = 0; i < req->probes; i++)
|
||||
get_random_bytes(((uint32_t *) map->initval)+i, 4);
|
||||
map->elements = 0;
|
||||
map->hashsize = req->hashsize;
|
||||
map->probes = req->probes;
|
||||
map->resize = req->resize;
|
||||
memset(map->cidr, 0, 30 * sizeof(unsigned char));
|
||||
map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
|
||||
if (!map->members) {
|
||||
DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set->data = map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
HASH_CREATE(nethash, ip_set_ip_t)
|
||||
HASH_DESTROY(nethash)
|
||||
|
||||
harray_free(map->members);
|
||||
kfree(map);
|
||||
HASH_FLUSH_CIDR(nethash, ip_set_ip_t)
|
||||
|
||||
set->data = NULL;
|
||||
static inline void
|
||||
__nethash_list_header(const struct ip_set_nethash *map,
|
||||
struct ip_set_req_nethash_create *header)
|
||||
{
|
||||
}
|
||||
|
||||
static void flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
|
||||
memset(map->cidr, 0, 30 * sizeof(unsigned char));
|
||||
map->elements = 0;
|
||||
}
|
||||
HASH_LIST_HEADER(nethash)
|
||||
HASH_LIST_MEMBERS_SIZE(nethash, ip_set_ip_t)
|
||||
HASH_LIST_MEMBERS(nethash, ip_set_ip_t)
|
||||
|
||||
static void list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_nethash *map = set->data;
|
||||
struct ip_set_req_nethash_create *header = data;
|
||||
|
||||
header->hashsize = map->hashsize;
|
||||
header->probes = map->probes;
|
||||
header->resize = map->resize;
|
||||
}
|
||||
|
||||
static int list_members_size(const struct ip_set *set)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
|
||||
return (map->hashsize * sizeof(ip_set_ip_t));
|
||||
}
|
||||
|
||||
static void list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_nethash *map = set->data;
|
||||
ip_set_ip_t i, *elem;
|
||||
|
||||
for (i = 0; i < map->hashsize; i++) {
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
|
||||
((ip_set_ip_t *)data)[i] = *elem;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ip_set_type ip_set_nethash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
.create = &create,
|
||||
.destroy = &destroy,
|
||||
.flush = &flush,
|
||||
.reqsize = sizeof(struct ip_set_req_nethash),
|
||||
.addip = &addip,
|
||||
.addip_kernel = &addip_kernel,
|
||||
.retry = &retry,
|
||||
.delip = &delip,
|
||||
.delip_kernel = &delip_kernel,
|
||||
.testip = &testip,
|
||||
.testip_kernel = &testip_kernel,
|
||||
.header_size = sizeof(struct ip_set_req_nethash_create),
|
||||
.list_header = &list_header,
|
||||
.list_members_size = &list_members_size,
|
||||
.list_members = &list_members,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
IP_SET_RTYPE(nethash, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
@@ -474,17 +217,4 @@ MODULE_DESCRIPTION("nethash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
static int __init ip_set_nethash_init(void)
|
||||
{
|
||||
init_max_page_size();
|
||||
return ip_set_register_set_type(&ip_set_nethash);
|
||||
}
|
||||
|
||||
static void __exit ip_set_nethash_fini(void)
|
||||
{
|
||||
/* FIXME: possible race with ip_set_create() */
|
||||
ip_set_unregister_set_type(&ip_set_nethash);
|
||||
}
|
||||
|
||||
module_init(ip_set_nethash_init);
|
||||
module_exit(ip_set_nethash_fini);
|
||||
REGISTER_MODULE(nethash)
|
||||
|
@@ -2,9 +2,9 @@
|
||||
#define __IP_SET_NETHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "nethash"
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
|
||||
struct ip_set_nethash {
|
||||
ip_set_ip_t *members; /* the nethash proper */
|
||||
@@ -12,8 +12,9 @@ struct ip_set_nethash {
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
unsigned char cidr[30]; /* CIDR sizes */
|
||||
void *initval[0]; /* initvals for jhash_1word */
|
||||
uint8_t cidr[30]; /* CIDR sizes */
|
||||
uint16_t nets[30]; /* nr of nets by CIDR sizes */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_nethash_create {
|
||||
@@ -24,32 +25,7 @@ struct ip_set_req_nethash_create {
|
||||
|
||||
struct ip_set_req_nethash {
|
||||
ip_set_ip_t ip;
|
||||
unsigned char cidr;
|
||||
uint8_t cidr;
|
||||
};
|
||||
|
||||
static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
|
||||
|
||||
static inline ip_set_ip_t
|
||||
pack(ip_set_ip_t ip, unsigned char cidr)
|
||||
{
|
||||
ip_set_ip_t addr, *paddr = &addr;
|
||||
unsigned char n, t, *a;
|
||||
|
||||
addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
|
||||
#ifdef __KERNEL__
|
||||
DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
|
||||
#endif
|
||||
n = cidr / 8;
|
||||
t = cidr % 8;
|
||||
a = &((unsigned char *)paddr)[n];
|
||||
*a = *a /(1 << (8 - t)) + shifts[t];
|
||||
#ifdef __KERNEL__
|
||||
DP("n: %u, t: %u, a: %u", n, t, *a);
|
||||
DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
|
||||
HIPQUAD(ip), cidr, NIPQUAD(addr));
|
||||
#endif
|
||||
|
||||
return ntohl(addr);
|
||||
}
|
||||
|
||||
#endif /* __IP_SET_NETHASH_H */
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
/* Copyright (C) 2003-2008 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
|
||||
@@ -12,9 +12,6 @@
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include "ip_set.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
@@ -23,113 +20,37 @@
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_portmap.h"
|
||||
|
||||
/* We must handle non-linear skbs */
|
||||
static inline ip_set_ip_t
|
||||
get_port(const struct sk_buff *skb, u_int32_t flags)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
#else
|
||||
struct iphdr *iph = skb->nh.iph;
|
||||
#endif
|
||||
u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
switch (iph->protocol) {
|
||||
case IPPROTO_TCP: {
|
||||
struct tcphdr tcph;
|
||||
|
||||
/* See comments at tcp_match in ip_tables.c */
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
|
||||
#else
|
||||
if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
|
||||
#endif
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags & IPSET_SRC ?
|
||||
tcph.source : tcph.dest);
|
||||
}
|
||||
case IPPROTO_UDP: {
|
||||
struct udphdr udph;
|
||||
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
|
||||
#else
|
||||
if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
|
||||
#endif
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags & IPSET_SRC ?
|
||||
udph.source : udph.dest);
|
||||
}
|
||||
default:
|
||||
return INVALID_PORT;
|
||||
}
|
||||
}
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static inline int
|
||||
__testport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
|
||||
portmap_test(const struct ip_set *set, ip_set_ip_t *hash_port,
|
||||
ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_portmap *map = set->data;
|
||||
const struct ip_set_portmap *map = set->data;
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
if (port < map->first_ip || port > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_port = port;
|
||||
DP("set: %s, port:%u, %u", set->name, port, *hash_port);
|
||||
return !!test_bit(port - map->first_port, map->members);
|
||||
return !!test_bit(port - map->first_ip, map->members);
|
||||
}
|
||||
|
||||
static int
|
||||
testport(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_port)
|
||||
{
|
||||
const struct ip_set_req_portmap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_portmap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_portmap),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __testport(set, req->port, hash_port);
|
||||
}
|
||||
|
||||
static int
|
||||
testport_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_port,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
int res;
|
||||
ip_set_ip_t port = get_port(skb, flags[index]);
|
||||
|
||||
DP("flag %s port %u", flags[index] & IPSET_SRC ? "SRC" : "DST", port);
|
||||
if (port == INVALID_PORT)
|
||||
#define KADT_CONDITION \
|
||||
if (ip == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
res = __testport(set, port, hash_port);
|
||||
|
||||
return (res < 0 ? 0 : res);
|
||||
}
|
||||
UADT(portmap, test)
|
||||
KADT(portmap, test, get_port)
|
||||
|
||||
static inline int
|
||||
__addport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
|
||||
portmap_add(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_portmap *map = set->data;
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
if (port < map->first_ip || port > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (test_and_set_bit(port - map->first_port, map->members))
|
||||
if (test_and_set_bit(port - map->first_ip, map->members))
|
||||
return -EEXIST;
|
||||
|
||||
*hash_port = port;
|
||||
@@ -137,44 +58,17 @@ __addport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
addport(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_port)
|
||||
{
|
||||
const struct ip_set_req_portmap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_portmap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_portmap),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __addport(set, req->port, hash_port);
|
||||
}
|
||||
|
||||
static int
|
||||
addport_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_port,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
ip_set_ip_t port = get_port(skb, flags[index]);
|
||||
|
||||
if (port == INVALID_PORT)
|
||||
return -EINVAL;
|
||||
|
||||
return __addport(set, port, hash_port);
|
||||
}
|
||||
UADT(portmap, add)
|
||||
KADT(portmap, add, get_port)
|
||||
|
||||
static inline int
|
||||
__delport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
|
||||
portmap_del(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_portmap *map = set->data;
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
if (port < map->first_ip || port > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (!test_and_clear_bit(port - map->first_port, map->members))
|
||||
if (!test_and_clear_bit(port - map->first_ip, map->members))
|
||||
return -EEXIST;
|
||||
|
||||
*hash_port = port;
|
||||
@@ -182,160 +76,39 @@ __delport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
delport(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_port)
|
||||
UADT(portmap, del)
|
||||
KADT(portmap, del, get_port)
|
||||
|
||||
static inline int
|
||||
__portmap_create(const struct ip_set_req_portmap_create *req,
|
||||
struct ip_set_portmap *map)
|
||||
{
|
||||
const struct ip_set_req_portmap *req = data;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_portmap)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_portmap),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
return __delport(set, req->port, hash_port);
|
||||
}
|
||||
|
||||
static int
|
||||
delport_kernel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_port,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
ip_set_ip_t port = get_port(skb, flags[index]);
|
||||
|
||||
if (port == INVALID_PORT)
|
||||
return -EINVAL;
|
||||
|
||||
return __delport(set, port, hash_port);
|
||||
}
|
||||
|
||||
static int create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
int newbytes;
|
||||
const struct ip_set_req_portmap_create *req = data;
|
||||
struct ip_set_portmap *map;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_portmap_create)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_portmap_create),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DP("from %u to %u", req->from, req->to);
|
||||
|
||||
if (req->from > req->to) {
|
||||
DP("bad port range");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big (max %d ports)",
|
||||
MAX_RANGE+1);
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_portmap), GFP_KERNEL);
|
||||
if (!map) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_portmap));
|
||||
return -ENOMEM;
|
||||
}
|
||||
map->first_port = req->from;
|
||||
map->last_port = req->to;
|
||||
newbytes = bitmap_bytes(req->from, req->to);
|
||||
map->members = kmalloc(newbytes, GFP_KERNEL);
|
||||
if (!map->members) {
|
||||
DP("out of memory for %d bytes", newbytes);
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(map->members, 0, newbytes);
|
||||
|
||||
set->data = map;
|
||||
return 0;
|
||||
return bitmap_bytes(req->from, req->to);
|
||||
}
|
||||
|
||||
static void destroy(struct ip_set *set)
|
||||
BITMAP_CREATE(portmap)
|
||||
BITMAP_DESTROY(portmap)
|
||||
BITMAP_FLUSH(portmap)
|
||||
|
||||
static inline void
|
||||
__portmap_list_header(const struct ip_set_portmap *map,
|
||||
struct ip_set_req_portmap_create *header)
|
||||
{
|
||||
struct ip_set_portmap *map = set->data;
|
||||
|
||||
kfree(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_portmap *map = set->data;
|
||||
memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
|
||||
}
|
||||
BITMAP_LIST_HEADER(portmap)
|
||||
BITMAP_LIST_MEMBERS_SIZE(portmap)
|
||||
BITMAP_LIST_MEMBERS(portmap)
|
||||
|
||||
static void list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_portmap *map = set->data;
|
||||
struct ip_set_req_portmap_create *header = data;
|
||||
|
||||
DP("list_header %u %u", map->first_port, map->last_port);
|
||||
|
||||
header->from = map->first_port;
|
||||
header->to = map->last_port;
|
||||
}
|
||||
|
||||
static int list_members_size(const struct ip_set *set)
|
||||
{
|
||||
const struct ip_set_portmap *map = set->data;
|
||||
|
||||
return bitmap_bytes(map->first_port, map->last_port);
|
||||
}
|
||||
|
||||
static void list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_portmap *map = set->data;
|
||||
int bytes = bitmap_bytes(map->first_port, map->last_port);
|
||||
|
||||
memcpy(data, map->members, bytes);
|
||||
}
|
||||
|
||||
static struct ip_set_type ip_set_portmap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.features = IPSET_TYPE_PORT | IPSET_DATA_SINGLE,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
.create = &create,
|
||||
.destroy = &destroy,
|
||||
.flush = &flush,
|
||||
.reqsize = sizeof(struct ip_set_req_portmap),
|
||||
.addip = &addport,
|
||||
.addip_kernel = &addport_kernel,
|
||||
.delip = &delport,
|
||||
.delip_kernel = &delport_kernel,
|
||||
.testip = &testport,
|
||||
.testip_kernel = &testport_kernel,
|
||||
.header_size = sizeof(struct ip_set_req_portmap_create),
|
||||
.list_header = &list_header,
|
||||
.list_members_size = &list_members_size,
|
||||
.list_members = &list_members,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
IP_SET_TYPE(portmap, IPSET_TYPE_PORT | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("portmap type of IP sets");
|
||||
|
||||
static int __init ip_set_portmap_init(void)
|
||||
{
|
||||
return ip_set_register_set_type(&ip_set_portmap);
|
||||
}
|
||||
|
||||
static void __exit ip_set_portmap_fini(void)
|
||||
{
|
||||
/* FIXME: possible race with ip_set_create() */
|
||||
ip_set_unregister_set_type(&ip_set_portmap);
|
||||
}
|
||||
|
||||
module_init(ip_set_portmap_init);
|
||||
module_exit(ip_set_portmap_fini);
|
||||
REGISTER_MODULE(portmap)
|
||||
|
@@ -2,15 +2,15 @@
|
||||
#define __IP_SET_PORTMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
|
||||
#define SETTYPE_NAME "portmap"
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
#define INVALID_PORT (MAX_RANGE + 1)
|
||||
|
||||
struct ip_set_portmap {
|
||||
void *members; /* the portmap proper */
|
||||
ip_set_ip_t first_port; /* host byte order, included in range */
|
||||
ip_set_ip_t last_port; /* host byte order, included in range */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
size_t size; /* size of the ipmap proper */
|
||||
};
|
||||
|
||||
struct ip_set_req_portmap_create {
|
||||
@@ -19,7 +19,7 @@ struct ip_set_req_portmap_create {
|
||||
};
|
||||
|
||||
struct ip_set_req_portmap {
|
||||
ip_set_ip_t port;
|
||||
ip_set_ip_t ip;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_PORTMAP_H */
|
||||
|
332
extensions/ipset/ip_set_setlist.c
Normal file
332
extensions/ipset/ip_set_setlist.c
Normal file
@@ -0,0 +1,332 @@
|
||||
/* Copyright (C) 2008 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 implementing an IP set type: the setlist type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
#include "ip_set_setlist.h"
|
||||
|
||||
/*
|
||||
* before ==> index, ref
|
||||
* after ==> ref, index
|
||||
*/
|
||||
|
||||
static inline bool
|
||||
next_index_eq(const struct ip_set_setlist *map, int i, ip_set_id_t index)
|
||||
{
|
||||
return i < map->size && map->index[i] == index;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_utest(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_setlist *map = set->data;
|
||||
const struct ip_set_req_setlist *req = data;
|
||||
ip_set_id_t index, ref = IP_SET_INVALID_ID;
|
||||
int i, res = 0;
|
||||
struct ip_set *s;
|
||||
|
||||
if (req->before && req->ref[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
index = __ip_set_get_byname(req->name, &s);
|
||||
if (index == IP_SET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
if (req->ref[0] != '\0') {
|
||||
ref = __ip_set_get_byname(req->ref, &s);
|
||||
if (ref == IP_SET_INVALID_ID) {
|
||||
res = -EEXIST;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++) {
|
||||
if (req->before && map->index[i] == index) {
|
||||
res = next_index_eq(map, i + 1, ref);
|
||||
break;
|
||||
} else if (!req->before) {
|
||||
if ((ref == IP_SET_INVALID_ID
|
||||
&& map->index[i] == index)
|
||||
|| (map->index[i] == ref
|
||||
&& next_index_eq(map, i + 1, index))) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ref != IP_SET_INVALID_ID)
|
||||
__ip_set_put_byindex(ref);
|
||||
finish:
|
||||
__ip_set_put_byindex(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_ktest(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i, res = 0;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID
|
||||
&& res == 0; i++)
|
||||
res = ip_set_testip_kernel(map->index[i], skb, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int
|
||||
insert_setlist(struct ip_set_setlist *map, int i, ip_set_id_t index)
|
||||
{
|
||||
ip_set_id_t tmp;
|
||||
int j;
|
||||
|
||||
DP("i: %u, last %u\n", i, map->index[map->size - 1]);
|
||||
if (i >= map->size || map->index[map->size - 1] != IP_SET_INVALID_ID)
|
||||
return -ERANGE;
|
||||
|
||||
for (j = i; j < map->size
|
||||
&& index != IP_SET_INVALID_ID; j++) {
|
||||
tmp = map->index[j];
|
||||
map->index[j] = index;
|
||||
index = tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_uadd(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
const struct ip_set_req_setlist *req = data;
|
||||
ip_set_id_t index, ref = IP_SET_INVALID_ID;
|
||||
int i, res = -ERANGE;
|
||||
struct ip_set *s;
|
||||
|
||||
if (req->before && req->ref[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
index = __ip_set_get_byname(req->name, &s);
|
||||
if (index == IP_SET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
/* "Loop detection" */
|
||||
if (strcmp(s->type->typename, "setlist") == 0)
|
||||
goto finish;
|
||||
|
||||
if (req->ref[0] != '\0') {
|
||||
ref = __ip_set_get_byname(req->ref, &s);
|
||||
if (ref == IP_SET_INVALID_ID) {
|
||||
res = -EEXIST;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < map->size; i++) {
|
||||
if (map->index[i] != ref)
|
||||
continue;
|
||||
if (req->before)
|
||||
res = insert_setlist(map, i, index);
|
||||
else
|
||||
res = insert_setlist(map,
|
||||
ref == IP_SET_INVALID_ID ? i : i + 1,
|
||||
index);
|
||||
break;
|
||||
}
|
||||
if (ref != IP_SET_INVALID_ID)
|
||||
__ip_set_put_byindex(ref);
|
||||
/* In case of success, we keep the reference to the set */
|
||||
finish:
|
||||
if (res != 0)
|
||||
__ip_set_put_byindex(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_kadd(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i, res = -EINVAL;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID
|
||||
&& res != 0; i++)
|
||||
res = ip_set_addip_kernel(map->index[i], skb, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
unshift_setlist(struct ip_set_setlist *map, int i)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = i; j < map->size - 1; j++)
|
||||
map->index[j] = map->index[j+1];
|
||||
map->index[map->size-1] = IP_SET_INVALID_ID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_udel(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
const struct ip_set_req_setlist *req = data;
|
||||
ip_set_id_t index, ref = IP_SET_INVALID_ID;
|
||||
int i, res = -EEXIST;
|
||||
struct ip_set *s;
|
||||
|
||||
if (req->before && req->ref[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
index = __ip_set_get_byname(req->name, &s);
|
||||
if (index == IP_SET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
if (req->ref[0] != '\0') {
|
||||
ref = __ip_set_get_byname(req->ref, &s);
|
||||
if (ref == IP_SET_INVALID_ID)
|
||||
goto finish;
|
||||
}
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++) {
|
||||
if (req->before) {
|
||||
if (map->index[i] == index
|
||||
&& next_index_eq(map, i + 1, ref)) {
|
||||
res = unshift_setlist(map, i);
|
||||
break;
|
||||
}
|
||||
} else if (ref == IP_SET_INVALID_ID) {
|
||||
if (map->index[i] == index) {
|
||||
res = unshift_setlist(map, i);
|
||||
break;
|
||||
}
|
||||
} else if (map->index[i] == ref
|
||||
&& next_index_eq(map, i + 1, index)) {
|
||||
res = unshift_setlist(map, i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ref != IP_SET_INVALID_ID)
|
||||
__ip_set_put_byindex(ref);
|
||||
finish:
|
||||
__ip_set_put_byindex(index);
|
||||
/* In case of success, release the reference to the set */
|
||||
if (res == 0)
|
||||
__ip_set_put_byindex(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_kdel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i, res = -EINVAL;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID
|
||||
&& res != 0; i++)
|
||||
res = ip_set_delip_kernel(map->index[i], skb, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
struct ip_set_setlist *map;
|
||||
const struct ip_set_req_setlist_create *req = data;
|
||||
int i;
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_setlist) +
|
||||
req->size * sizeof(ip_set_id_t), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
map->size = req->size;
|
||||
for (i = 0; i < map->size; i++)
|
||||
map->index[i] = IP_SET_INVALID_ID;
|
||||
|
||||
set->data = map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++)
|
||||
__ip_set_put_byindex(map->index[i]);
|
||||
|
||||
kfree(map);
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++) {
|
||||
__ip_set_put_byindex(map->index[i]);
|
||||
map->index[i] = IP_SET_INVALID_ID;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_setlist *map = set->data;
|
||||
struct ip_set_req_setlist_create *header = data;
|
||||
|
||||
header->size = map->size;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_list_members_size(const struct ip_set *set)
|
||||
{
|
||||
const struct ip_set_setlist *map = set->data;
|
||||
|
||||
return map->size * sizeof(ip_set_id_t);
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->size; i++)
|
||||
*((ip_set_id_t *)data + i) = ip_set_id(map->index[i]);
|
||||
}
|
||||
|
||||
IP_SET_TYPE(setlist, IPSET_TYPE_SETNAME | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("setlist type of IP sets");
|
||||
|
||||
REGISTER_MODULE(setlist)
|
26
extensions/ipset/ip_set_setlist.h
Normal file
26
extensions/ipset/ip_set_setlist.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __IP_SET_SETLIST_H
|
||||
#define __IP_SET_SETLIST_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define SETTYPE_NAME "setlist"
|
||||
|
||||
#define IP_SET_SETLIST_ADD_AFTER 0
|
||||
#define IP_SET_SETLIST_ADD_BEFORE 1
|
||||
|
||||
struct ip_set_setlist {
|
||||
uint8_t size;
|
||||
ip_set_id_t index[0];
|
||||
};
|
||||
|
||||
struct ip_set_req_setlist_create {
|
||||
uint8_t size;
|
||||
};
|
||||
|
||||
struct ip_set_req_setlist {
|
||||
char name[IP_SET_MAXNAMELEN];
|
||||
char ref[IP_SET_MAXNAMELEN];
|
||||
uint8_t before;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_SETLIST_H */
|
@@ -87,14 +87,9 @@ is given. Bindings are not affected by the flush operation.
|
||||
Rename a set. Set identified by to-setname must not exist.
|
||||
.TP
|
||||
.BI "-W, --swap " "\fIfrom-setname\fP \fIto-setname\fP"
|
||||
Swap two sets as they referenced in the Linux kernel.
|
||||
.B
|
||||
iptables
|
||||
rules or
|
||||
.B
|
||||
ipset
|
||||
bindings pointing to the content of from-setname will point to
|
||||
the content of to-setname and vice versa. Both sets must exist.
|
||||
Swap the content of two sets, or in another words,
|
||||
exchange the name of two sets. The referred sets must exist and
|
||||
identical type of sets can be swapped only.
|
||||
.TP
|
||||
.BI "-L, --list " "[\fIsetname\fP]"
|
||||
List the entries and bindings for the specified set, or for
|
||||
@@ -203,12 +198,12 @@ ipset supports the following set types:
|
||||
The ipmap set type uses a memory range, where each bit represents
|
||||
one IP address. An ipmap set can store up to 65536 (B-class network)
|
||||
IP addresses. The ipmap set type is very fast and memory cheap, great
|
||||
for use when one want to match certain IPs in a range. Using the
|
||||
for use when one want to match certain IPs in a range. If the optional
|
||||
.B "--netmask"
|
||||
option with a CIDR netmask value between 0-32 when creating an ipmap
|
||||
set, you will be able to store and match network addresses: i.e an
|
||||
IP address will be in the set if the value resulted by masking the address
|
||||
with the specified netmask can be found in the set.
|
||||
parameter is specified with a CIDR netmask value between 1-31 then
|
||||
network addresses are stored in the given set: i.e an
|
||||
IP address will be in the set if the network address, which is resulted
|
||||
by masking the address with the specified netmask, can be found in the set.
|
||||
.P
|
||||
Options to use when creating an ipmap set:
|
||||
.TP
|
||||
@@ -225,17 +220,16 @@ When the optional
|
||||
.B "--netmask"
|
||||
parameter specified, network addresses will be
|
||||
stored in the set instead of IP addresses, and the from-IP parameter
|
||||
must be a network address.
|
||||
must be a network address. The CIDR-netmask value must be between 1-31.
|
||||
.SS macipmap
|
||||
The macipmap set type uses a memory range, where each 8 bytes
|
||||
represents one IP and a MAC addresses. A macipmap set type can store
|
||||
up to 65536 (B-class network) IP addresses with MAC.
|
||||
When adding an entry to a macipmap set, you must specify the entry as
|
||||
.I IP:MAC.
|
||||
.I IP,MAC.
|
||||
When deleting or testing macipmap entries, the
|
||||
.I :MAC
|
||||
part is not mandatory. (The old "%" separation token instead of ":", i.e
|
||||
IP%MAC is accepted as well.)
|
||||
.I ,MAC
|
||||
part is not mandatory.
|
||||
.P
|
||||
Options to use when creating an macipmap set:
|
||||
.TP
|
||||
@@ -279,12 +273,12 @@ Create a portmap set from the specified range.
|
||||
The iphash set type uses a hash to store IP addresses.
|
||||
In order to avoid clashes in the hash double-hashing, and as a last
|
||||
resort, dynamic growing of the hash performed. The iphash set type is
|
||||
great to store random addresses. By supplyig the
|
||||
great to store random addresses. If the optional
|
||||
.B "--netmask"
|
||||
option with a CIDR netmask value between 0-32 at creating the set,
|
||||
you will be able to store and match network addresses instead: i.e
|
||||
an IP address will be in the set if the value of the address
|
||||
masked with the specified netmask can be found in the set.
|
||||
parameter is specified with a CIDR netmask value between 1-31 then
|
||||
network addresses are stored in the given set: i.e an
|
||||
IP address will be in the set if the network address, which is resulted
|
||||
by masking the address with the specified netmask, can be found in the set.
|
||||
.P
|
||||
Options to use when creating an iphash set:
|
||||
.TP
|
||||
@@ -306,21 +300,22 @@ number of double-hashing.
|
||||
When the optional
|
||||
.B "--netmask"
|
||||
parameter specified, network addresses will be
|
||||
stored in the set instead of IP addresses.
|
||||
stored in the set instead of IP addresses. The CIDR-netmask value must
|
||||
be between 1-31.
|
||||
.P
|
||||
The iphash type of sets can store up to 65536 entries. If a set is full,
|
||||
no new entries can be added to it.
|
||||
.P
|
||||
Sets created by zero valued resize parameter won't be resized at all.
|
||||
The lookup time in an iphash type of set approximately linearly grows with
|
||||
The lookup time in an iphash type of set grows approximately linearly with
|
||||
the value of the
|
||||
.B
|
||||
probes
|
||||
parameter. At the same time higher
|
||||
parameter. In general higher
|
||||
.B
|
||||
probes
|
||||
values result a better utilized hash while smaller values
|
||||
produce a larger, sparse hash.
|
||||
probe
|
||||
value results better utilized hash while smaller value
|
||||
produces larger, sparser hash.
|
||||
.SS nethash
|
||||
The nethash set type uses a hash to store different size of
|
||||
network addresses. The
|
||||
@@ -349,18 +344,18 @@ an IP to the hash could not be performed after
|
||||
The nethash type of sets can store up to 65536 entries. If a set is full,
|
||||
no new entries can be added to it.
|
||||
.P
|
||||
An IP address will be in a nethash type of set if it is in any of the
|
||||
netblocks added to the set and the matching always start from the smallest
|
||||
size of netblock (most specific netmask) to the biggest ones (least
|
||||
An IP address will be in a nethash type of set if it belongs to any of the
|
||||
netblocks added to the set. The matching always start from the smallest
|
||||
size of netblock (most specific netmask) to the largest ones (least
|
||||
specific netmasks). When adding/deleting IP addresses
|
||||
to a nethash set by the
|
||||
.I
|
||||
SET
|
||||
netfilter kernel module, it will be added/deleted by the smallest
|
||||
netblock size which can be found in the set.
|
||||
netblock size which can be found in the set, or by /31 if the set is empty.
|
||||
.P
|
||||
The lookup time in a nethash type of set is approximately linearly
|
||||
grows with the times of the
|
||||
The lookup time in a nethash type of set grows approximately linearly
|
||||
with the times of the
|
||||
.B
|
||||
probes
|
||||
parameter and the number of different mask parameters in the hash.
|
||||
@@ -374,8 +369,7 @@ store up to 65536 (B-class network) IP addresses with all possible port
|
||||
values. When adding, deleting and testing values in an ipporthash type of
|
||||
set, the entries must be specified as
|
||||
.B
|
||||
"IP:port".
|
||||
(Old "IP%port" format accepted as well.)
|
||||
"IP,port".
|
||||
.P
|
||||
The ipporthash types of sets evaluates two src/dst parameters of the
|
||||
.I
|
||||
@@ -411,6 +405,94 @@ number of double-hashing.
|
||||
.P
|
||||
The same resizing, speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS ipportiphash
|
||||
The ipportiphash set type uses a hash to store IP address,port and IP
|
||||
address triples. The first IP address must come form a maximum /16
|
||||
sized network or range while the port number and the second IP address
|
||||
parameters are arbitrary. When adding, deleting and testing values in an
|
||||
ipportiphash type of set, the entries must be specified as
|
||||
.B
|
||||
"IP,port,IP".
|
||||
.P
|
||||
The ipportiphash types of sets evaluates three src/dst parameters of the
|
||||
.I
|
||||
set
|
||||
match and
|
||||
.I
|
||||
SET
|
||||
target.
|
||||
.P
|
||||
Options to use when creating an ipportiphash set:
|
||||
.TP
|
||||
.BR "--from " from-IP
|
||||
.TP
|
||||
.BR "--to " to-IP
|
||||
Create an ipportiphash set from the specified range.
|
||||
.TP
|
||||
.BR "--network " IP/mask
|
||||
Create an ipportiphash set from the specified network.
|
||||
.TP
|
||||
.BR "--hashsize " hashsize
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
.BR "--probes " probes
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
.BR "--resize " percent
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
.B
|
||||
probes
|
||||
number of double-hashing.
|
||||
.P
|
||||
The same resizing, speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS ipportnethash
|
||||
The ipportnethash set type uses a hash to store IP address, port, and
|
||||
network address triples. The IP address must come form a maximum /16
|
||||
sized network or range while the port number and the network address
|
||||
parameters are arbitrary, but the size of the network address must be
|
||||
between /1-/31. When adding, deleting
|
||||
and testing values in an ipportnethash type of set, the entries must be
|
||||
specified as
|
||||
.B
|
||||
"IP,port,IP/cidr-size".
|
||||
.P
|
||||
The ipportnethash types of sets evaluates three src/dst parameters of the
|
||||
.I
|
||||
set
|
||||
match and
|
||||
.I
|
||||
SET
|
||||
target.
|
||||
.P
|
||||
Options to use when creating an ipportnethash set:
|
||||
.TP
|
||||
.BR "--from " from-IP
|
||||
.TP
|
||||
.BR "--to " to-IP
|
||||
Create an ipporthash set from the specified range.
|
||||
.TP
|
||||
.BR "--network " IP/mask
|
||||
Create an ipporthash set from the specified network.
|
||||
.TP
|
||||
.BR "--hashsize " hashsize
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
.BR "--probes " probes
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
.BR "--resize " percent
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
.B
|
||||
probes
|
||||
number of double-hashing.
|
||||
.P
|
||||
The same resizing, speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS iptree
|
||||
The iptree set type uses a tree to store IP addresses, optionally
|
||||
with timeout values.
|
||||
@@ -424,7 +506,7 @@ If a set was created with a nonzero valued
|
||||
.B "--timeout"
|
||||
parameter then one may add IP addresses to the set with a specific
|
||||
timeout value using the syntax
|
||||
.I IP:timeout-value.
|
||||
.I IP,timeout-value.
|
||||
Similarly to the hash types, the iptree type of sets can store up to 65536
|
||||
entries.
|
||||
.SS iptreemap
|
||||
@@ -432,12 +514,67 @@ The iptreemap set type uses a tree to store IP addresses or networks,
|
||||
where the last octet of an IP address are stored in a bitmap.
|
||||
As input entry, you can add IP addresses, CIDR blocks or network ranges
|
||||
to the set. Network ranges can be specified in the format
|
||||
.I IP1:IP2
|
||||
.I IP1-IP2
|
||||
.P
|
||||
Options to use when creating an iptreemap set:
|
||||
.TP
|
||||
.BR "--gc " value
|
||||
How often the garbage collection should be called, in seconds (default 300)
|
||||
.SS setlist
|
||||
The setlist type uses a simple list in which you can store sets. By the
|
||||
.I
|
||||
ipset
|
||||
command you can add, delete and test sets in a setlist type of set.
|
||||
You can specify the sets as
|
||||
.B
|
||||
"setname[,after|before,setname]".
|
||||
By default new sets are added after (appended to) the existing
|
||||
elements. Setlist type of sets cannot be added to a setlist type of set.
|
||||
.P
|
||||
Options to use when creating a setlist type of set:
|
||||
.TP
|
||||
.BR "--size " size
|
||||
Create a setlist type of set with the given size (default 8).
|
||||
.P
|
||||
By the
|
||||
.I
|
||||
set
|
||||
match or
|
||||
.I
|
||||
SET
|
||||
target of
|
||||
.I
|
||||
iptables
|
||||
you can test, add or delete entries in the sets. The match
|
||||
will try to find a matching IP address/port in the sets and
|
||||
the target will try to add the IP address/port to the first set
|
||||
to which it can be added. The number of src,dst options of
|
||||
the match and target are important: sets which eats more src,dst
|
||||
parameters than specified are skipped, while sets with equal
|
||||
or less parameters are checked, elements added. For example
|
||||
if
|
||||
.I
|
||||
a
|
||||
and
|
||||
.I
|
||||
b
|
||||
are setlist type of sets then in the command
|
||||
.TP
|
||||
iptables -m set --match-set a src,dst -j SET --add-set b src,dst
|
||||
the match and target will skip any set in
|
||||
.I a
|
||||
and
|
||||
.I b
|
||||
which stores
|
||||
data triples, but will check all sets with single or double
|
||||
data storage in
|
||||
.I a
|
||||
set and add src to the first single or src,dst to the first double
|
||||
data storage set in
|
||||
.I b.
|
||||
.P
|
||||
You can imagine a setlist type of set as an ordered union of
|
||||
the set elements.
|
||||
.SH GENERAL RESTRICTIONS
|
||||
Setnames starting with colon (:) cannot be defined. Zero valued set
|
||||
entries cannot be used with hash type of sets.
|
||||
@@ -447,6 +584,8 @@ If you want to store same size subnets from a given network
|
||||
If you want to store random same size networks (say random /24 blocks),
|
||||
use the iphash set type. If you have got random size of netblocks,
|
||||
use nethash.
|
||||
.P
|
||||
Old separator tokens (':' and '%") are still accepted.
|
||||
.SH DIAGNOSTICS
|
||||
Various error messages are printed to standard error. The exit code
|
||||
is 0 for correct functioning. Errors which appear to be caused by
|
||||
|
@@ -7,23 +7,22 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdarg.h>
|
||||
#include <netdb.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
/* #include <asm/bitops.h> */
|
||||
#include <stdio.h> /* *printf, perror, sscanf, fdopen */
|
||||
#include <string.h> /* mem*, str* */
|
||||
#include <errno.h> /* errno, perror */
|
||||
#include <time.h> /* time, ctime */
|
||||
#include <netdb.h> /* gethostby*, getnetby*, getservby* */
|
||||
#include <stdlib.h> /* exit, malloc, free, strtol, getenv, mkstemp */
|
||||
#include <unistd.h> /* read, close, fork, exec*, unlink */
|
||||
#include <sys/types.h> /* open, wait, socket, *sockopt, umask */
|
||||
#include <sys/stat.h> /* open, umask */
|
||||
#include <sys/wait.h> /* wait */
|
||||
#include <sys/socket.h> /* socket, *sockopt, gethostby*, inet_* */
|
||||
#include <netinet/in.h> /* inet_* */
|
||||
#include <fcntl.h> /* open */
|
||||
#include <arpa/inet.h> /* htonl, inet_* */
|
||||
#include <stdarg.h> /* va_* */
|
||||
#include <dlfcn.h> /* dlopen */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
@@ -31,11 +30,11 @@
|
||||
#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
|
||||
#endif
|
||||
|
||||
#define IPSET_VERSION "2.3.2a"
|
||||
#define IPSET_VERSION "2.4.5"
|
||||
|
||||
char program_name[] = "ipset";
|
||||
char program_version[] = IPSET_VERSION;
|
||||
const char *xtables_libdir = XTABLES_LIBDIR;
|
||||
const char *ipset_libdir = IPSET_LIB_DIR;
|
||||
|
||||
/* The list of loaded set types */
|
||||
static struct settype *all_settypes = NULL;
|
||||
@@ -53,7 +52,8 @@ void *restore_data = NULL;
|
||||
struct ip_set_restore *restore_set = NULL;
|
||||
size_t restore_offset = 0;
|
||||
socklen_t restore_size;
|
||||
unsigned int g_line = 0;
|
||||
unsigned restore_line = 0;
|
||||
unsigned warn_once = 0;
|
||||
|
||||
#define TEMPFILE_PATTERN "/ipsetXXXXXX"
|
||||
|
||||
@@ -78,9 +78,10 @@ static const char cmdflags[] = { ' ', /* CMD_NONE */
|
||||
#define OPT_QUIET 0x0004U /* -q */
|
||||
#define OPT_DEBUG 0x0008U /* -z */
|
||||
#define OPT_BINDING 0x0010U /* -b */
|
||||
#define NUMBER_OF_OPT 5
|
||||
#define OPT_RESOLVE 0x0020U /* -r */
|
||||
#define NUMBER_OF_OPT 6
|
||||
static const char optflags[] =
|
||||
{ 'n', 's', 'q', 'z', 'b' };
|
||||
{ 'n', 's', 'q', 'z', 'b', 'r' };
|
||||
|
||||
static struct option opts_long[] = {
|
||||
/* set operations */
|
||||
@@ -108,6 +109,7 @@ static struct option opts_long[] = {
|
||||
{"sorted", 0, 0, 's'},
|
||||
{"quiet", 0, 0, 'q'},
|
||||
{"binding", 1, 0, 'b'},
|
||||
{"resolve", 0, 0, 'r'},
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
/* debug (if compiled with it) */
|
||||
@@ -119,11 +121,11 @@ static struct option opts_long[] = {
|
||||
{"help", 2, 0, 'H'},
|
||||
|
||||
/* end */
|
||||
{0}
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static char opts_short[] =
|
||||
"-N:X::F::E:W:L::S::RA:D:T:B:U:nsqzb:Vh::H::";
|
||||
"-N:X::F::E:W:L::S::RA:D:T:B:U:nrsqzb:Vh::H::";
|
||||
|
||||
/* Table of legal combinations of commands and options. If any of the
|
||||
* given commands make an option legal, that option is legal.
|
||||
@@ -135,21 +137,21 @@ static char opts_short[] =
|
||||
|
||||
static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = {
|
||||
/* -n -s -q -z -b */
|
||||
/*CREATE*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*DESTROY*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*FLUSH*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*RENAME*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*SWAP*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*LIST*/ {' ', ' ', 'x', ' ', 'x'},
|
||||
/*SAVE*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*RESTORE*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*ADD*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*DEL*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*TEST*/ {'x', 'x', ' ', ' ', ' '},
|
||||
/*BIND*/ {'x', 'x', ' ', ' ', '+'},
|
||||
/*UNBIND*/ {'x', 'x', ' ', ' ', 'x'},
|
||||
/*HELP*/ {'x', 'x', 'x', ' ', 'x'},
|
||||
/*VERSION*/ {'x', 'x', 'x', ' ', 'x'},
|
||||
/*CREATE*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*DESTROY*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*FLUSH*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*RENAME*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*SWAP*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*LIST*/ {' ', ' ', 'x', ' ', 'x', ' '},
|
||||
/*SAVE*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*RESTORE*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*ADD*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*DEL*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*TEST*/ {'x', 'x', ' ', ' ', ' ', 'x'},
|
||||
/*BIND*/ {'x', 'x', ' ', ' ', '+', 'x'},
|
||||
/*UNBIND*/ {'x', 'x', ' ', ' ', 'x', 'x'},
|
||||
/*HELP*/ {'x', 'x', 'x', ' ', 'x', 'x'},
|
||||
/*VERSION*/ {'x', 'x', 'x', ' ', 'x', 'x'},
|
||||
};
|
||||
|
||||
/* Main parser function */
|
||||
@@ -163,18 +165,18 @@ static void exit_tryhelp(int status)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
void exit_error(enum exittype status, const char *msg, ...)
|
||||
void exit_error(int status, const char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (!option_quiet) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, msg);
|
||||
fprintf(stderr, "%s v%s: ", program_name, program_version);
|
||||
vfprintf(stderr, msg, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
if (g_line)
|
||||
fprintf(stderr, "Restore failed at line %u:\n", g_line);
|
||||
if (restore_line)
|
||||
fprintf(stderr, "Restore failed at line %u:\n", restore_line);
|
||||
if (status == PARAMETER_PROBLEM)
|
||||
exit_tryhelp(status);
|
||||
if (status == VERSION_PROBLEM)
|
||||
@@ -188,9 +190,9 @@ void exit_error(enum exittype status, const char *msg, ...)
|
||||
|
||||
static void ipset_printf(const char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (!option_quiet) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, msg);
|
||||
vfprintf(stdout, msg, args);
|
||||
va_end(args);
|
||||
@@ -198,7 +200,7 @@ static void ipset_printf(const char *msg, ...)
|
||||
}
|
||||
}
|
||||
|
||||
static void generic_opt_check(int command, int options)
|
||||
static void generic_opt_check(int command, unsigned int options)
|
||||
{
|
||||
int i, j, legal = 0;
|
||||
|
||||
@@ -233,7 +235,7 @@ static void generic_opt_check(int command, int options)
|
||||
}
|
||||
}
|
||||
|
||||
static char opt2char(int option)
|
||||
static char opt2char(unsigned int option)
|
||||
{
|
||||
const char *ptr;
|
||||
for (ptr = optflags; option > 1; option >>= 1, ptr++);
|
||||
@@ -241,12 +243,12 @@ static char opt2char(int option)
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
static char cmd2char(int option)
|
||||
static char cmd2char(int cmd)
|
||||
{
|
||||
if (option <= CMD_NONE || option > NUMBER_OF_CMD)
|
||||
if (cmd <= CMD_NONE || cmd > NUMBER_OF_CMD)
|
||||
return ' ';
|
||||
|
||||
return cmdflags[option];
|
||||
return cmdflags[cmd];
|
||||
}
|
||||
|
||||
/* From iptables.c ... */
|
||||
@@ -266,6 +268,7 @@ static char *get_modprobe(void)
|
||||
switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
|
||||
case -1: goto fail;
|
||||
case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */
|
||||
default: ; /* nothing */
|
||||
}
|
||||
if (ret[strlen(ret)-1]=='\n')
|
||||
ret[strlen(ret)-1]=0;
|
||||
@@ -295,8 +298,8 @@ static int ipset_insmod(const char *modname, const char *modprobe)
|
||||
|
||||
switch (fork()) {
|
||||
case 0:
|
||||
argv[0] = (char *)modprobe;
|
||||
argv[1] = (char *)modname;
|
||||
argv[0] = (char *) modprobe;
|
||||
argv[1] = (char *) modname;
|
||||
argv[2] = NULL;
|
||||
execv(argv[0], argv);
|
||||
|
||||
@@ -334,7 +337,7 @@ static void kernel_error(unsigned cmd, int err)
|
||||
struct translate_error {
|
||||
int err;
|
||||
unsigned cmd;
|
||||
char *message;
|
||||
const char *message;
|
||||
} table[] =
|
||||
{ /* Generic error codes */
|
||||
{ EPERM, 0, "Missing capability" },
|
||||
@@ -352,11 +355,12 @@ static void kernel_error(unsigned cmd, int err)
|
||||
{ ENOENT, 0, "Unknown set" },
|
||||
{ EAGAIN, 0, "Sets are busy, try again later" },
|
||||
{ ERANGE, CMD_CREATE, "No free slot remained to add a new set" },
|
||||
{ ERANGE, 0, "IP/port is outside of the set" },
|
||||
{ ERANGE, 0, "IP/port/element is outside of the set or set is full" },
|
||||
{ ENOEXEC, CMD_CREATE, "Invalid parameters to create a set" },
|
||||
{ ENOEXEC, CMD_SWAP, "Sets with different types cannot be swapped" },
|
||||
{ EEXIST, CMD_CREATE, "Set already exists" },
|
||||
{ EEXIST, CMD_RENAME, "Set with new name already exists" },
|
||||
{ EEXIST, 0, "Set specified as element does not exist" },
|
||||
{ EBUSY, 0, "Set is in use, operation not permitted" },
|
||||
};
|
||||
for (i = 0; i < sizeof(table)/sizeof(struct translate_error); i++) {
|
||||
@@ -409,7 +413,7 @@ static void kernel_getfrom(unsigned cmd, void *data, socklen_t * size)
|
||||
kernel_error(cmd, errno);
|
||||
}
|
||||
|
||||
static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
|
||||
static int kernel_sendto_handleerrno(unsigned cmd,
|
||||
void *data, socklen_t size)
|
||||
{
|
||||
int res = wrapped_setsockopt(data, size);
|
||||
@@ -432,7 +436,7 @@ static void kernel_sendto(unsigned cmd, void *data, size_t size)
|
||||
kernel_error(cmd, errno);
|
||||
}
|
||||
|
||||
static int kernel_getfrom_handleerrno(unsigned cmd, void *data, size_t * size)
|
||||
static int kernel_getfrom_handleerrno(unsigned cmd, void *data, socklen_t *size)
|
||||
{
|
||||
int res = wrapped_getsockopt(data, size);
|
||||
|
||||
@@ -471,7 +475,7 @@ static void check_protocolversion(void)
|
||||
req_version.version, IP_SET_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
static void set_command(unsigned *cmd, const int newcmd)
|
||||
static void set_command(int *cmd, int newcmd)
|
||||
{
|
||||
if (*cmd != CMD_NONE)
|
||||
exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
|
||||
@@ -513,18 +517,17 @@ char *ipset_strdup(const char *s)
|
||||
return p;
|
||||
}
|
||||
|
||||
void ipset_free(void **data)
|
||||
void ipset_free(void *data)
|
||||
{
|
||||
if (*data == NULL)
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
free(*data);
|
||||
*data = NULL;
|
||||
free(data);
|
||||
}
|
||||
|
||||
static struct option *merge_options(struct option *oldopts,
|
||||
const struct option *newopts,
|
||||
unsigned int *option_offset)
|
||||
int *option_offset)
|
||||
{
|
||||
unsigned int num_old, num_new, i;
|
||||
struct option *merge;
|
||||
@@ -564,7 +567,7 @@ static char *ip_tonetwork(const struct in_addr *addr)
|
||||
{
|
||||
struct netent *net;
|
||||
|
||||
if ((net = getnetbyaddr((long) ntohl(addr->s_addr),
|
||||
if ((net = getnetbyaddr(ntohl(addr->s_addr),
|
||||
AF_INET)) != NULL) {
|
||||
DP("%s", net->n_name);
|
||||
return (char *) net->n_name;
|
||||
@@ -591,7 +594,8 @@ char *ip_tostring(ip_set_ip_t ip, unsigned options)
|
||||
return inet_ntoa(addr);
|
||||
}
|
||||
|
||||
char *binding_ip_tostring(struct set *set, ip_set_ip_t ip, unsigned options)
|
||||
char *binding_ip_tostring(struct set *set UNUSED,
|
||||
ip_set_ip_t ip, unsigned options)
|
||||
{
|
||||
return ip_tostring(ip, options);
|
||||
}
|
||||
@@ -636,7 +640,7 @@ void parse_ip(const char *str, ip_set_ip_t * ip)
|
||||
void parse_mask(const char *str, ip_set_ip_t * mask)
|
||||
{
|
||||
struct in_addr addr;
|
||||
unsigned int bits;
|
||||
int bits;
|
||||
|
||||
DP("%s", str);
|
||||
|
||||
@@ -711,12 +715,12 @@ int
|
||||
string_to_number(const char *str, unsigned int min, unsigned int max,
|
||||
ip_set_ip_t *port)
|
||||
{
|
||||
long number;
|
||||
unsigned long number;
|
||||
char *end;
|
||||
|
||||
/* Handle hex, octal, etc. */
|
||||
errno = 0;
|
||||
number = strtol(str, &end, 0);
|
||||
number = strtoul(str, &end, 0);
|
||||
if (*end == '\0' && end != str) {
|
||||
/* we parsed a number, let's see if we want this */
|
||||
if (errno != ERANGE && min <= number && number <= max) {
|
||||
@@ -731,12 +735,11 @@ static int
|
||||
string_to_port(const char *str, ip_set_ip_t *port)
|
||||
{
|
||||
struct servent *service;
|
||||
|
||||
|
||||
if ((service = getservbyname(str, "tcp")) != NULL) {
|
||||
*port = ntohs((unsigned short) service->s_port);
|
||||
*port = ntohs((uint16_t) service->s_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -771,7 +774,8 @@ static struct settype *settype_find(const char *typename)
|
||||
|
||||
static struct settype *settype_load(const char *typename)
|
||||
{
|
||||
char path[256];
|
||||
char path[sizeof(IPSET_LIB_DIR) + sizeof(IPSET_LIB_NAME) +
|
||||
strlen(typename)];
|
||||
struct settype *settype;
|
||||
|
||||
/* do some search in list */
|
||||
@@ -780,8 +784,7 @@ static struct settype *settype_load(const char *typename)
|
||||
return settype; /* found */
|
||||
|
||||
/* Else we have to load it */
|
||||
snprintf(path, sizeof(path), "%s/libipset_%s.so",
|
||||
xtables_libdir, typename);
|
||||
sprintf(path, IPSET_LIB_DIR IPSET_LIB_NAME, typename);
|
||||
|
||||
if (dlopen(path, RTLD_NOW)) {
|
||||
/* Found library. */
|
||||
@@ -859,7 +862,7 @@ void settype_register(struct settype *settype)
|
||||
}
|
||||
|
||||
/* Find set functions */
|
||||
static struct set *set_find_byid(ip_set_id_t id)
|
||||
struct set *set_find_byid(ip_set_id_t id)
|
||||
{
|
||||
struct set *set = NULL;
|
||||
ip_set_id_t i;
|
||||
@@ -876,7 +879,7 @@ static struct set *set_find_byid(ip_set_id_t id)
|
||||
return set;
|
||||
}
|
||||
|
||||
static struct set *set_find_byname(const char *name)
|
||||
struct set *set_find_byname(const char *name)
|
||||
{
|
||||
struct set *set = NULL;
|
||||
ip_set_id_t i;
|
||||
@@ -910,7 +913,7 @@ static ip_set_id_t set_find_free_index(const char *name)
|
||||
name);
|
||||
}
|
||||
|
||||
if (idx == IP_SET_INVALID_ID)
|
||||
if (idx == IP_SET_INVALID_ID)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Set %s cannot be restored, "
|
||||
"max number of set %u reached",
|
||||
@@ -1137,6 +1140,11 @@ static size_t save_bindings(void *data, size_t offset, size_t len)
|
||||
if (!(set && set_list[hash->binding]))
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"Save binding failed, try again later.");
|
||||
if (!set->settype->bindip_tostring)
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"Internal error, binding is not supported with set %s"
|
||||
" of settype %s\n",
|
||||
set->name, set->settype->typename);
|
||||
printf("-B %s %s -b %s\n",
|
||||
set->name,
|
||||
set->settype->bindip_tostring(set, hash->ip, OPT_NUMERIC),
|
||||
@@ -1263,7 +1271,7 @@ static int try_save_sets(const char name[IP_SET_MAXNAMELEN])
|
||||
printf("COMMIT\n");
|
||||
now = time(NULL);
|
||||
printf("# Completed on %s", ctime(&now));
|
||||
ipset_free(&data);
|
||||
ipset_free(data);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1297,7 +1305,7 @@ static char *newargv[255];
|
||||
static int newargc = 0;
|
||||
|
||||
/* Build faked argv from parsed line */
|
||||
static void build_argv(int line, char *buffer) {
|
||||
static void build_argv(unsigned line, char *buffer) {
|
||||
char *ptr;
|
||||
int i;
|
||||
|
||||
@@ -1309,7 +1317,7 @@ static void build_argv(int line, char *buffer) {
|
||||
ptr = strtok(buffer, " \t\n");
|
||||
newargv[newargc++] = ipset_strdup(ptr);
|
||||
while ((ptr = strtok(NULL, " \t\n")) != NULL) {
|
||||
if ((newargc + 1) < sizeof(newargv)/sizeof(char *))
|
||||
if ((newargc + 1) < (int)(sizeof(newargv)/sizeof(char *)))
|
||||
newargv[newargc++] = ipset_strdup(ptr);
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
@@ -1319,14 +1327,14 @@ static void build_argv(int line, char *buffer) {
|
||||
|
||||
static FILE *create_tempfile(void)
|
||||
{
|
||||
char buffer[1024];
|
||||
char buffer[1024], __tmpdir[] = "/tmp";
|
||||
char *tmpdir = NULL;
|
||||
char *filename;
|
||||
int fd;
|
||||
FILE *file;
|
||||
|
||||
if (!(tmpdir = getenv("TMPDIR")) && !(tmpdir = getenv("TMP")))
|
||||
tmpdir = "/tmp";
|
||||
tmpdir = __tmpdir;
|
||||
filename = ipset_malloc(strlen(tmpdir) + strlen(TEMPFILE_PATTERN) + 1);
|
||||
strcpy(filename, tmpdir);
|
||||
strcat(filename, TEMPFILE_PATTERN);
|
||||
@@ -1357,7 +1365,7 @@ static void set_restore(char *argv0)
|
||||
char buffer[1024];
|
||||
char *ptr, *name = NULL;
|
||||
char cmd = ' ';
|
||||
int line = 0, first_pass, i, bindings = 0;
|
||||
int first_pass, i, bindings = 0;
|
||||
struct settype *settype = NULL;
|
||||
struct ip_set_req_setnames *header;
|
||||
ip_set_id_t idx;
|
||||
@@ -1371,12 +1379,13 @@ static void set_restore(char *argv0)
|
||||
load_set_list(IPSET_TOKEN_ALL, &idx,
|
||||
IP_SET_OP_LIST_SIZE, CMD_RESTORE);
|
||||
|
||||
restore_line = 0;
|
||||
restore_size = sizeof(struct ip_set_req_setnames)/* header */
|
||||
+ sizeof(struct ip_set_restore); /* marker */
|
||||
DP("restore_size: %u", restore_size);
|
||||
/* First pass: calculate required amount of data */
|
||||
while (fgets(buffer, sizeof(buffer), in)) {
|
||||
line++;
|
||||
restore_line++;
|
||||
|
||||
if (buffer[0] == '\n')
|
||||
continue;
|
||||
@@ -1399,7 +1408,7 @@ static void set_restore(char *argv0)
|
||||
|| ptr[2] != '\0') {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Line %u does not start as a valid restore command\n",
|
||||
line);
|
||||
restore_line);
|
||||
}
|
||||
cmd = ptr[1];
|
||||
/* setname */
|
||||
@@ -1408,7 +1417,7 @@ static void set_restore(char *argv0)
|
||||
if (ptr == NULL)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Missing set name in line %u\n",
|
||||
line);
|
||||
restore_line);
|
||||
DP("cmd %c", cmd);
|
||||
switch (cmd) {
|
||||
case 'N': {
|
||||
@@ -1418,11 +1427,11 @@ static void set_restore(char *argv0)
|
||||
if (ptr == NULL)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Missing settype in line %u\n",
|
||||
line);
|
||||
restore_line);
|
||||
if (bindings)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid line %u: create must precede bindings\n",
|
||||
line);
|
||||
restore_line);
|
||||
settype = check_set_typename(ptr);
|
||||
restore_size += sizeof(struct ip_set_restore)
|
||||
+ settype->create_size;
|
||||
@@ -1435,11 +1444,11 @@ static void set_restore(char *argv0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Add IP to set %s in line %u without "
|
||||
"preceding corresponding create set line\n",
|
||||
ptr, line);
|
||||
ptr, restore_line);
|
||||
if (bindings)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid line %u: adding entries must precede bindings\n",
|
||||
line);
|
||||
restore_line);
|
||||
restore_size += settype->adt_size;
|
||||
DP("restore_size (A): %u", restore_size);
|
||||
break;
|
||||
@@ -1453,7 +1462,7 @@ static void set_restore(char *argv0)
|
||||
default: {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Unrecognized restore command in line %u\n",
|
||||
line);
|
||||
restore_line);
|
||||
}
|
||||
} /* end of switch */
|
||||
}
|
||||
@@ -1470,15 +1479,15 @@ static void set_restore(char *argv0)
|
||||
|
||||
/* Rewind to scan the file again */
|
||||
fseek(in, 0L, SEEK_SET);
|
||||
first_pass = line;
|
||||
line = 0;
|
||||
first_pass = restore_line;
|
||||
restore_line = 0;
|
||||
|
||||
/* Initialize newargv/newargc */
|
||||
newargv[newargc++] = ipset_strdup(argv0);
|
||||
|
||||
/* Second pass: build up restore request */
|
||||
while (fgets(buffer, sizeof(buffer), in)) {
|
||||
line++;
|
||||
restore_line++;
|
||||
|
||||
if (buffer[0] == '\n')
|
||||
continue;
|
||||
@@ -1488,7 +1497,7 @@ static void set_restore(char *argv0)
|
||||
goto do_restore;
|
||||
DP("restoring: %s", buffer);
|
||||
/* Build faked argv, argc */
|
||||
build_argv(line, buffer);
|
||||
build_argv(restore_line, buffer);
|
||||
for (i = 0; i < newargc; i++)
|
||||
DP("argv[%u]: %s", i, newargv[i]);
|
||||
|
||||
@@ -1580,7 +1589,7 @@ static int set_adtip(struct set *set, const char *adt,
|
||||
memcpy(data + sizeof(struct ip_set_req_adt),
|
||||
set->settype->data, set->settype->adt_size);
|
||||
|
||||
if (kernel_sendto_handleerrno(cmd, op, data, size) == -1)
|
||||
if (kernel_sendto_handleerrno(cmd, data, size) == -1)
|
||||
switch (op) {
|
||||
case IP_SET_OP_ADD_IP:
|
||||
exit_error(OTHER_PROBLEM, "%s is already in set %s.",
|
||||
@@ -1611,7 +1620,7 @@ static int set_adtip(struct set *set, const char *adt,
|
||||
return res;
|
||||
}
|
||||
|
||||
static void set_restore_add(struct set *set, const char *adt)
|
||||
static void set_restore_add(struct set *set, const char *adt UNUSED)
|
||||
{
|
||||
DP("%s %s", set->name, adt);
|
||||
/* Sanity checking */
|
||||
@@ -1641,9 +1650,14 @@ static int set_bind(struct set *set, const char *adt,
|
||||
DP("(%s, %s) -> %s", set ? set->name : IPSET_TOKEN_ALL, adt, binding);
|
||||
|
||||
/* Ugly */
|
||||
if (set && strcmp(set->settype->typename, "iptreemap") == 0)
|
||||
if (set != NULL
|
||||
&& ((strcmp(set->settype->typename, "iptreemap") == 0)
|
||||
|| (strcmp(set->settype->typename, "ipportiphash") == 0)
|
||||
|| (strcmp(set->settype->typename, "ipportnethash") == 0)
|
||||
|| (strcmp(set->settype->typename, "setlist") == 0)))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"iptreemap type of sets cannot be used at binding operations\n");
|
||||
"%s type of sets cannot be used at binding operations\n",
|
||||
set->settype->typename);
|
||||
/* Alloc memory for the data to send */
|
||||
size = sizeof(struct ip_set_req_bind);
|
||||
if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':')
|
||||
@@ -1671,7 +1685,7 @@ static int set_bind(struct set *set, const char *adt,
|
||||
}
|
||||
|
||||
if (op == IP_SET_OP_TEST_BIND_SET) {
|
||||
if (kernel_sendto_handleerrno(cmd, op, data, size) == -1) {
|
||||
if (kernel_sendto_handleerrno(cmd, data, size) == -1) {
|
||||
ipset_printf("%s in set %s is bound to %s.",
|
||||
adt, set->name, binding);
|
||||
res = 0;
|
||||
@@ -1717,8 +1731,14 @@ static void set_restore_bind(struct set *set,
|
||||
DP("%s -> %s", adt, binding);
|
||||
if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0)
|
||||
hash_restore->ip = 0;
|
||||
else
|
||||
else {
|
||||
if (!set->settype->bindip_parse)
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"Internal error, binding is not supported with set %s"
|
||||
" of settype %s\n",
|
||||
set->name, set->settype->typename);
|
||||
set->settype->bindip_parse(adt, &hash_restore->ip);
|
||||
}
|
||||
hash_restore->id = set->index;
|
||||
hash_restore->binding = (set_find_byname(binding))->index;
|
||||
DP("id %u, ip %u, binding %u",
|
||||
@@ -1738,6 +1758,12 @@ static void print_bindings(struct set *set,
|
||||
size_t offset = 0;
|
||||
struct ip_set_hash_list *hash;
|
||||
|
||||
if (offset < size && !printip)
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"Internal error, binding is not supported with set %s"
|
||||
" of settype %s\n",
|
||||
set->name, set->settype->typename);
|
||||
|
||||
while (offset < size) {
|
||||
hash = (struct ip_set_hash_list *) (data + offset);
|
||||
printf("%s -> %s\n",
|
||||
@@ -1750,7 +1776,7 @@ static void print_bindings(struct set *set,
|
||||
/* Help function to set_list() */
|
||||
static size_t print_set(void *data, unsigned options)
|
||||
{
|
||||
struct ip_set_list *setlist = (struct ip_set_list *) data;
|
||||
struct ip_set_list *setlist = data;
|
||||
struct set *set = set_list[setlist->index];
|
||||
struct settype *settype = set->settype;
|
||||
size_t offset;
|
||||
@@ -1784,7 +1810,8 @@ static size_t print_set(void *data, unsigned options)
|
||||
/* Print bindings */
|
||||
printf("Bindings:\n");
|
||||
offset += setlist->members_size;
|
||||
print_bindings(set,
|
||||
if (set->settype->bindip_tostring)
|
||||
print_bindings(set,
|
||||
data + offset, setlist->bindings_size, options,
|
||||
settype->bindip_tostring);
|
||||
|
||||
@@ -1801,6 +1828,10 @@ static int try_list_sets(const char name[IP_SET_MAXNAMELEN],
|
||||
socklen_t size, req_size;
|
||||
int res = 0;
|
||||
|
||||
/* Default is numeric listing */
|
||||
if (!(options & (OPT_RESOLVE|OPT_NUMERIC)))
|
||||
options |= OPT_NUMERIC;
|
||||
|
||||
DP("%s", name);
|
||||
/* Load set_list from kernel */
|
||||
size = req_size = load_set_list(name, &idx,
|
||||
@@ -1823,7 +1854,7 @@ static int try_list_sets(const char name[IP_SET_MAXNAMELEN],
|
||||
while (size != req_size)
|
||||
size += print_set(data + size, options);
|
||||
|
||||
ipset_free(&data);
|
||||
ipset_free(data);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1853,13 +1884,6 @@ static void list_sets(const char name[IP_SET_MAXNAMELEN], unsigned options)
|
||||
*/
|
||||
static void set_help(const struct settype *settype)
|
||||
{
|
||||
#ifdef IPSET_DEBUG
|
||||
char debughelp[] =
|
||||
" --debug -z Enable debugging\n\n";
|
||||
#else
|
||||
char debughelp[] = "\n";
|
||||
#endif
|
||||
|
||||
printf("%s v%s\n\n"
|
||||
"Usage: %s -N new-set settype [options]\n"
|
||||
" %s -[XFLSH] [set] [options]\n"
|
||||
@@ -1910,10 +1934,15 @@ static void set_help(const struct settype *settype)
|
||||
" Prints version information\n\n"
|
||||
"Options:\n"
|
||||
" --sorted -s Numeric sort of the IPs in -L\n"
|
||||
" --numeric -n Numeric output of addresses in a -L\n"
|
||||
" --numeric -n Numeric output of addresses in a -L (default)\n"
|
||||
" --resolve -r Try to resolve addresses in a -L\n"
|
||||
" --quiet -q Suppress any output to stdout and stderr.\n"
|
||||
" --binding -b Specifies the binding for -B\n");
|
||||
printf(debughelp);
|
||||
#ifdef IPSET_DEBUG
|
||||
printf(" --debug -z Enable debugging\n\n");
|
||||
#else
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
if (settype != NULL) {
|
||||
printf("Type '%s' specific:\n", settype->typename);
|
||||
@@ -1921,7 +1950,7 @@ static void set_help(const struct settype *settype)
|
||||
}
|
||||
}
|
||||
|
||||
static int find_cmd(const char option)
|
||||
static int find_cmd(int option)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1932,7 +1961,7 @@ static int find_cmd(const char option)
|
||||
return CMD_NONE;
|
||||
}
|
||||
|
||||
static int parse_adt_cmdline(unsigned command,
|
||||
static int parse_adt_cmdline(int command,
|
||||
const char *name,
|
||||
char *adt,
|
||||
struct set **set,
|
||||
@@ -1982,7 +2011,7 @@ static int parse_adt_cmdline(unsigned command,
|
||||
int parse_commandline(int argc, char *argv[])
|
||||
{
|
||||
int res = 0;
|
||||
unsigned command = CMD_NONE;
|
||||
int command = CMD_NONE;
|
||||
unsigned options = 0;
|
||||
int c;
|
||||
|
||||
@@ -2146,6 +2175,11 @@ int parse_commandline(int argc, char *argv[])
|
||||
add_option(&options, OPT_NUMERIC);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (!(options & OPT_NUMERIC))
|
||||
add_option(&options, OPT_RESOLVE);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
add_option(&options, OPT_SORTED);
|
||||
break;
|
||||
@@ -2169,7 +2203,7 @@ int parse_commandline(int argc, char *argv[])
|
||||
|
||||
case 1: /* non option */
|
||||
printf("Bad argument `%s'\n", optarg);
|
||||
exit_tryhelp(2);
|
||||
exit_tryhelp(PARAMETER_PROBLEM);
|
||||
break; /*always good */
|
||||
|
||||
default:{
|
||||
@@ -2272,6 +2306,8 @@ int parse_commandline(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case CMD_BIND:
|
||||
fprintf(stderr, "Warning: binding will be removed from the next release.\n"
|
||||
"Please replace bindigs with sets of ipportmap and ipportiphash types\n");
|
||||
if (restore)
|
||||
set_restore_bind(set, adt, binding);
|
||||
else
|
||||
@@ -2299,11 +2335,6 @@ int parse_commandline(int argc, char *argv[])
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *p = getenv("XTABLES_LIBDIR");
|
||||
|
||||
if (p != NULL)
|
||||
xtables_libdir = p;
|
||||
|
||||
return parse_commandline(argc, argv);
|
||||
|
||||
}
|
||||
|
@@ -20,12 +20,13 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <getopt.h> /* struct option */
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define IPSET_LIB_NAME "/libipset_%s.so"
|
||||
#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
|
||||
|
||||
#define LIST_TRIES 5
|
||||
@@ -117,7 +118,7 @@ struct settype {
|
||||
size_t adt_size;
|
||||
|
||||
/* Function which parses command options */
|
||||
ip_set_ip_t (*adt_parser) (unsigned cmd, const char *optarg, void *data);
|
||||
ip_set_ip_t (*adt_parser) (int cmd, const char *optarg, void *data);
|
||||
|
||||
/*
|
||||
* Printing
|
||||
@@ -156,7 +157,7 @@ struct settype {
|
||||
/* Internal data */
|
||||
void *header;
|
||||
void *data;
|
||||
unsigned int option_offset;
|
||||
int option_offset;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
@@ -164,7 +165,7 @@ extern void settype_register(struct settype *settype);
|
||||
|
||||
/* extern void unregister_settype(set_type_t *set_type); */
|
||||
|
||||
extern void exit_error(enum exittype status, const char *msg, ...);
|
||||
extern void exit_error(int status, const char *msg, ...);
|
||||
|
||||
extern char *binding_ip_tostring(struct set *set,
|
||||
ip_set_ip_t ip, unsigned options);
|
||||
@@ -181,11 +182,21 @@ extern int string_to_number(const char *str, unsigned int min, unsigned int max,
|
||||
|
||||
extern void *ipset_malloc(size_t size);
|
||||
extern char *ipset_strdup(const char *);
|
||||
extern void ipset_free(void **data);
|
||||
extern void ipset_free(void *data);
|
||||
|
||||
extern struct set *set_find_byname(const char *name);
|
||||
extern struct set *set_find_byid(ip_set_id_t id);
|
||||
|
||||
extern unsigned warn_once;
|
||||
|
||||
#define BITSPERBYTE (8*sizeof(char))
|
||||
#define ID2BYTE(id) ((id)/BITSPERBYTE)
|
||||
#define ID2MASK(id) (1 << ((id)%BITSPERBYTE))
|
||||
#define test_bit(id, heap) ((((char *)(heap))[ID2BYTE(id)] & ID2MASK(id)) != 0)
|
||||
|
||||
#define UNUSED __attribute__ ((unused))
|
||||
#define CONSTRUCTOR(module) \
|
||||
void __attribute__ ((constructor)) module##_init(void); \
|
||||
void module##_init(void)
|
||||
|
||||
#endif /* __IPSET_H */
|
||||
|
@@ -15,24 +15,14 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
#include "ip_set_iphash.h"
|
||||
#include "ip_set_jhash.h"
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_iphash.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
@@ -41,10 +31,10 @@
|
||||
#define OPT_CREATE_NETMASK 0x08U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void create_init(void *data)
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_iphash_create *mydata =
|
||||
(struct ip_set_req_iphash_create *) data;
|
||||
struct ip_set_req_iphash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
@@ -57,7 +47,8 @@ static void create_init(void *data)
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_iphash_create *mydata =
|
||||
(struct ip_set_req_iphash_create *) data;
|
||||
@@ -125,31 +116,25 @@ static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void create_final(void *data, unsigned int flags)
|
||||
static void
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
#ifdef IPSET_DEBUG
|
||||
struct ip_set_req_iphash_create *mydata =
|
||||
(struct ip_set_req_iphash_create *) data;
|
||||
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{"hashsize", 1, 0, '1'},
|
||||
{"probes", 1, 0, '2'},
|
||||
{"resize", 1, 0, '3'},
|
||||
{"netmask", 1, 0, '4'},
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "netmask", .has_arg = required_argument, .val = '4'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_iphash *mydata =
|
||||
(struct ip_set_req_iphash *) data;
|
||||
struct ip_set_req_iphash *mydata = data;
|
||||
|
||||
parse_ip(arg, &mydata->ip);
|
||||
if (!mydata->ip)
|
||||
@@ -163,12 +148,11 @@ static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void initheader(struct set *set, const void *data)
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
struct ip_set_req_iphash_create *header =
|
||||
(struct ip_set_req_iphash_create *) data;
|
||||
struct ip_set_iphash *map =
|
||||
(struct ip_set_iphash *) set->settype->header;
|
||||
const struct ip_set_req_iphash_create *header = data;
|
||||
struct ip_set_iphash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_iphash));
|
||||
map->hashsize = header->hashsize;
|
||||
@@ -187,16 +171,16 @@ mask_to_bits(ip_set_ip_t mask)
|
||||
return bits;
|
||||
|
||||
maskaddr = 0xFFFFFFFE;
|
||||
while (--bits >= 0 && maskaddr != mask)
|
||||
while (--bits > 0 && maskaddr != mask)
|
||||
maskaddr <<= 1;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static void printheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iphash *mysetdata =
|
||||
(struct ip_set_iphash *) set->settype->header;
|
||||
struct ip_set_iphash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
@@ -207,8 +191,8 @@ static void printheader(struct set *set, unsigned int options)
|
||||
printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
static void printips(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
printips(struct set *set UNUSED, void *data, size_t len, unsigned options)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
@@ -221,10 +205,10 @@ static void printips(struct set *set, void *data, size_t len,
|
||||
}
|
||||
}
|
||||
|
||||
static void saveheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iphash *mysetdata =
|
||||
(struct ip_set_iphash *) set->settype->header;
|
||||
struct ip_set_iphash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --hashsize %u --probes %u --resize %u",
|
||||
set->name, set->settype->typename,
|
||||
@@ -236,8 +220,8 @@ static void saveheader(struct set *set, unsigned int options)
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void saveips(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
saveips(struct set *set UNUSED, void *data, size_t len, unsigned options)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
@@ -292,7 +276,7 @@ static struct settype settype_iphash = {
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void iphash_init(void)
|
||||
CONSTRUCTOR(iphash)
|
||||
{
|
||||
settype_register(&settype_iphash);
|
||||
|
||||
|
@@ -17,15 +17,12 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
/* #include <asm/bitops.h> */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipmap.h"
|
||||
#include "ipset.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
@@ -37,20 +34,20 @@
|
||||
#define OPT_ADDDEL_IP 0x01U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void create_init(void *data)
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *mydata =
|
||||
(struct ip_set_req_ipmap_create *) data;
|
||||
struct ip_set_req_ipmap_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
mydata->netmask = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *mydata =
|
||||
(struct ip_set_req_ipmap_create *) data;
|
||||
struct ip_set_req_ipmap_create *mydata = data;
|
||||
unsigned int bits;
|
||||
|
||||
DP("create_parse");
|
||||
@@ -116,15 +113,12 @@ static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define ERRSTRLEN 256
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void create_final(void *data, unsigned int flags)
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *mydata =
|
||||
(struct ip_set_req_ipmap_create *) data;
|
||||
struct ip_set_req_ipmap_create *mydata = data;
|
||||
ip_set_ip_t range;
|
||||
char errstr[ERRSTRLEN];
|
||||
|
||||
if (flags == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
@@ -154,7 +148,7 @@ static void create_final(void *data, unsigned int flags)
|
||||
if (flags & OPT_CREATE_NETMASK) {
|
||||
unsigned int mask_bits, netmask_bits;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
|
||||
if ((mydata->from & mydata->netmask) != mydata->from)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"%s is not a network address according to netmask %d\n",
|
||||
@@ -164,26 +158,14 @@ static void create_final(void *data, unsigned int flags)
|
||||
mask = range_to_mask(mydata->from, mydata->to, &mask_bits);
|
||||
if (!mask
|
||||
&& (mydata->from || mydata->to != 0xFFFFFFFF)) {
|
||||
strncpy(errstr, ip_tostring_numeric(mydata->from),
|
||||
ERRSTRLEN-2);
|
||||
errstr[ERRSTRLEN-1] = '\0';
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"%s-%s is not a full network (%x)\n",
|
||||
errstr,
|
||||
ip_tostring_numeric(mydata->to), mask);
|
||||
"You have to define a full network with --from"
|
||||
" and --to if you specify the --network option\n");
|
||||
}
|
||||
netmask_bits = mask_to_bits(mydata->netmask);
|
||||
|
||||
if (netmask_bits <= mask_bits) {
|
||||
strncpy(errstr, ip_tostring_numeric(mydata->from),
|
||||
ERRSTRLEN-2);
|
||||
errstr[ERRSTRLEN-1] = '\0';
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"%d netmask specifies larger or equal netblock than %s-%s (%d)\n",
|
||||
netmask_bits,
|
||||
errstr,
|
||||
ip_tostring_numeric(mydata->to),
|
||||
mask_bits);
|
||||
"%d netmask specifies larger or equal netblock than the network itself\n");
|
||||
}
|
||||
range = (1<<(netmask_bits - mask_bits)) - 1;
|
||||
} else {
|
||||
@@ -197,18 +179,18 @@ static void create_final(void *data, unsigned int flags)
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{"from", 1, 0, '1'},
|
||||
{"to", 1, 0, '2'},
|
||||
{"network", 1, 0, '3'},
|
||||
{"netmask", 1, 0, '4'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "netmask", .has_arg = required_argument, .val = '4'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipmap *mydata =
|
||||
(struct ip_set_req_ipmap *) data;
|
||||
struct ip_set_req_ipmap *mydata = data;
|
||||
|
||||
DP("ipmap: %p %p", arg, data);
|
||||
|
||||
@@ -222,12 +204,11 @@ static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void initheader(struct set *set, const void *data)
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *header =
|
||||
(struct ip_set_req_ipmap_create *) data;
|
||||
struct ip_set_ipmap *map =
|
||||
(struct ip_set_ipmap *) set->settype->header;
|
||||
const struct ip_set_req_ipmap_create *header = data;
|
||||
struct ip_set_ipmap *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipmap));
|
||||
map->first_ip = header->from;
|
||||
@@ -252,10 +233,10 @@ static void initheader(struct set *set, const void *data)
|
||||
DP("%i %i", map->hosts, map->sizeid );
|
||||
}
|
||||
|
||||
static void printheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata =
|
||||
(struct ip_set_ipmap *) set->settype->header;
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
@@ -265,11 +246,11 @@ static void printheader(struct set *set, unsigned int options)
|
||||
printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
static void printips_sorted(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
printips_sorted(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata =
|
||||
(struct ip_set_ipmap *) set->settype->header;
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
ip_set_ip_t id;
|
||||
|
||||
for (id = 0; id < mysetdata->sizeid; id++)
|
||||
@@ -280,10 +261,10 @@ static void printips_sorted(struct set *set, void *data, size_t len,
|
||||
options));
|
||||
}
|
||||
|
||||
static void saveheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata =
|
||||
(struct ip_set_ipmap *) set->settype->header;
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
@@ -297,11 +278,10 @@ static void saveheader(struct set *set, unsigned int options)
|
||||
mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
static void saveips(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata =
|
||||
(struct ip_set_ipmap *) set->settype->header;
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
ip_set_ip_t id;
|
||||
|
||||
DP("%s", set->name);
|
||||
@@ -355,7 +335,7 @@ static struct settype settype_ipmap = {
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void ipmap_init(void)
|
||||
CONSTRUCTOR(ipmap)
|
||||
{
|
||||
settype_register(&settype_ipmap);
|
||||
|
||||
|
@@ -15,24 +15,14 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
#include "ip_set_ipporthash.h"
|
||||
#include "ip_set_jhash.h"
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipporthash.h"
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
@@ -41,10 +31,10 @@
|
||||
#define OPT_CREATE_TO 0x20U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void create_init(void *data)
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *mydata =
|
||||
(struct ip_set_req_ipporthash_create *) data;
|
||||
struct ip_set_req_ipporthash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
@@ -55,10 +45,10 @@ static void create_init(void *data)
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *mydata =
|
||||
(struct ip_set_req_ipporthash_create *) data;
|
||||
struct ip_set_req_ipporthash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
@@ -146,10 +136,10 @@ static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void create_final(void *data, unsigned int flags)
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *mydata =
|
||||
(struct ip_set_req_ipporthash_create *) data;
|
||||
struct ip_set_req_ipporthash_create *mydata = data;
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
@@ -188,34 +178,42 @@ static void create_final(void *data, unsigned int flags)
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{"hashsize", 1, 0, '1'},
|
||||
{"probes", 1, 0, '2'},
|
||||
{"resize", 1, 0, '3'},
|
||||
{"from", 1, 0, '4'},
|
||||
{"to", 1, 0, '5'},
|
||||
{"network", 1, 0, '6'},
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '4'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '5'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '6'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipporthash *mydata =
|
||||
(struct ip_set_req_ipporthash *) data;
|
||||
struct ip_set_req_ipporthash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("ipporthash: %p %p", arg, data);
|
||||
|
||||
ptr = strsep(&tmp, ":%");
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,port.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp)
|
||||
parse_port(tmp, &mydata->port);
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address and port must be specified: ip%%port");
|
||||
free(saved);
|
||||
"IP address and port must be specified: ip,port");
|
||||
|
||||
if (!(mydata->ip || mydata->port))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address and port `%s' specified", arg);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
};
|
||||
|
||||
@@ -223,12 +221,11 @@ static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void initheader(struct set *set, const void *data)
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *header =
|
||||
(struct ip_set_req_ipporthash_create *) data;
|
||||
struct ip_set_ipporthash *map =
|
||||
(struct ip_set_ipporthash *) set->settype->header;
|
||||
const struct ip_set_req_ipporthash_create *header = data;
|
||||
struct ip_set_ipporthash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipporthash));
|
||||
map->hashsize = header->hashsize;
|
||||
@@ -238,10 +235,10 @@ static void initheader(struct set *set, const void *data)
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void printheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata =
|
||||
(struct ip_set_ipporthash *) set->settype->header;
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
@@ -250,11 +247,10 @@ static void printheader(struct set *set, unsigned int options)
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static void printips(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
printips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata =
|
||||
(struct ip_set_ipporthash *) set->settype->header;
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ipptr, ip;
|
||||
uint16_t port;
|
||||
@@ -264,7 +260,7 @@ static void printips(struct set *set, void *data, size_t len,
|
||||
if (*ipptr) {
|
||||
ip = (*ipptr>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) *ipptr;
|
||||
printf("%s:%s\n",
|
||||
printf("%s,%s\n",
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
}
|
||||
@@ -272,10 +268,10 @@ static void printips(struct set *set, void *data, size_t len,
|
||||
}
|
||||
}
|
||||
|
||||
static void saveheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata =
|
||||
(struct ip_set_ipporthash *) set->settype->header;
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
@@ -287,11 +283,10 @@ static void saveheader(struct set *set, unsigned int options)
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void saveips(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata =
|
||||
(struct ip_set_ipporthash *) set->settype->header;
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ipptr, ip;
|
||||
uint16_t port;
|
||||
@@ -301,7 +296,7 @@ static void saveips(struct set *set, void *data, size_t len,
|
||||
if (*ipptr) {
|
||||
ip = (*ipptr>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) *ipptr;
|
||||
printf("-A %s %s:%s\n", set->name,
|
||||
printf("-A %s %s,%s\n", set->name,
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
}
|
||||
@@ -311,15 +306,15 @@ static void saveips(struct set *set, void *data, size_t len,
|
||||
|
||||
static char buffer[22];
|
||||
|
||||
static char * unpack_ipport_tostring(struct set *set, ip_set_ip_t bip, unsigned options)
|
||||
static char *
|
||||
unpack_ipport_tostring(struct set *set, ip_set_ip_t bip, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata =
|
||||
(struct ip_set_ipporthash *) set->settype->header;
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
ip_set_ip_t ip, port;
|
||||
|
||||
ip = (bip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) bip;
|
||||
sprintf(buffer, "%s:%s",
|
||||
sprintf(buffer, "%s,%s",
|
||||
ip_tostring(ip, options), port_tostring(port, options));
|
||||
|
||||
return buffer;
|
||||
@@ -332,9 +327,9 @@ static void usage(void)
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-N set ipporthash --network IP/mask\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-A set IP:port\n"
|
||||
"-D set IP:port\n"
|
||||
"-T set IP:port\n");
|
||||
"-A set IP,port\n"
|
||||
"-D set IP,port\n"
|
||||
"-T set IP,port\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipporthash = {
|
||||
@@ -368,7 +363,7 @@ static struct settype settype_ipporthash = {
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void ipporthash_init(void)
|
||||
CONSTRUCTOR(ipporthash)
|
||||
{
|
||||
settype_register(&settype_ipporthash);
|
||||
|
||||
|
361
extensions/ipset/ipset_ipportiphash.c
Normal file
361
extensions/ipset/ipset_ipportiphash.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/* Copyright 2008 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 as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipportiphash.h"
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETWORK 0x08U
|
||||
#define OPT_CREATE_FROM 0x10U
|
||||
#define OPT_CREATE_TO 0x20U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipportiphash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = 1024;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipportiphash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '5':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '6':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipportiphash_create *mydata = data;
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
|
||||
/* --from --to */
|
||||
if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
} else {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be higher than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '4'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '5'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '6'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipportiphash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("ipportiphash: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,port,ip.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (!tmp)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and IP address must be specified: ip,port,ip");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_port(ptr, &mydata->port);
|
||||
if (tmp)
|
||||
parse_ip(tmp, &mydata->ip1);
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and IP address must be specified: ip,port,ip");
|
||||
if (!(mydata->ip || mydata->port || mydata->ip1))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address, port and IP address `%s' specified", arg);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipportiphash_create *header = data;
|
||||
struct ip_set_ipportiphash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipportiphash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static void
|
||||
printips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (ipptr->ip && ipptr->ip1) {
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("%s,%s,",
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
ip_tostring(ipptr->ip1, options));
|
||||
}
|
||||
offset += sizeof(struct ipportip);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" --hashsize %u --probes %u --resize %u\n",
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (ipptr->ip && ipptr->ip1) {
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("-A %s %s,%s,", set->name,
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
ip_tostring(ipptr->ip1, options));
|
||||
}
|
||||
offset += sizeof(struct ipportip);
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipportiphash --from IP --to IP\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-N set ipportiphash --network IP/mask\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-A set IP,port,IP\n"
|
||||
"-D set IP,port,IP\n"
|
||||
"-T set IP,port,IP\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipportiphash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipportiphash_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipportiphash),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipportiphash),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips, /* We only have the unsorted version */
|
||||
.printips_sorted = &printips,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipportiphash)
|
||||
{
|
||||
settype_register(&settype_ipportiphash);
|
||||
|
||||
}
|
426
extensions/ipset/ipset_ipportnethash.c
Normal file
426
extensions/ipset/ipset_ipportnethash.c
Normal file
@@ -0,0 +1,426 @@
|
||||
/* Copyright 2008 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 as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipportnethash.h"
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETWORK 0x08U
|
||||
#define OPT_CREATE_FROM 0x10U
|
||||
#define OPT_CREATE_TO 0x20U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipportnethash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = 1024;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipportnethash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '5':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '6':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipportnethash_create *mydata = data;
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
|
||||
/* --from --to */
|
||||
if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
} else {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be higher than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '4'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '5'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '6'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipportnethash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
ip_set_ip_t cidr;
|
||||
|
||||
DP("ipportnethash: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,port,net.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
if (!tmp)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and network address must be specified: ip,port,net");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_port(ptr, &mydata->port);
|
||||
if (!tmp)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and network address must be specified: ip,port,net");
|
||||
|
||||
ptr = strsep(&tmp, "/");
|
||||
if (tmp == NULL)
|
||||
if (cmd == CMD_TEST)
|
||||
cidr = 32;
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Missing /cidr from `%s'", arg);
|
||||
else
|
||||
if (string_to_number(tmp, 1, 31, &cidr))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Out of range cidr `%s' specified", arg);
|
||||
|
||||
mydata->cidr = cidr;
|
||||
|
||||
parse_ip(ptr, &mydata->ip1);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipportnethash_create *header = data;
|
||||
struct ip_set_ipportnethash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipportnethash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static char buf[20];
|
||||
|
||||
static char *
|
||||
unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED)
|
||||
{
|
||||
int i, j = 3;
|
||||
unsigned char a, b;
|
||||
|
||||
ip = htonl(ip);
|
||||
for (i = 3; i >= 0; i--)
|
||||
if (((unsigned char *)&ip)[i] != 0) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
|
||||
a = ((unsigned char *)&ip)[j];
|
||||
if (a <= 128) {
|
||||
a = (a - 1) * 2;
|
||||
b = 7;
|
||||
} else if (a <= 192) {
|
||||
a = (a - 129) * 4;
|
||||
b = 6;
|
||||
} else if (a <= 224) {
|
||||
a = (a - 193) * 8;
|
||||
b = 5;
|
||||
} else if (a <= 240) {
|
||||
a = (a - 225) * 16;
|
||||
b = 4;
|
||||
} else if (a <= 248) {
|
||||
a = (a - 241) * 32;
|
||||
b = 3;
|
||||
} else if (a <= 252) {
|
||||
a = (a - 249) * 64;
|
||||
b = 2;
|
||||
} else if (a <= 254) {
|
||||
a = (a - 253) * 128;
|
||||
b = 1;
|
||||
} else {
|
||||
a = b = 0;
|
||||
}
|
||||
((unsigned char *)&ip)[j] = a;
|
||||
b += j * 8;
|
||||
|
||||
sprintf(buf, "%u.%u.%u.%u/%u",
|
||||
((unsigned char *)&ip)[0],
|
||||
((unsigned char *)&ip)[1],
|
||||
((unsigned char *)&ip)[2],
|
||||
((unsigned char *)&ip)[3],
|
||||
b);
|
||||
|
||||
DP("%s %s", ip_tostring(ntohl(ip), 0), buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
printips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (ipptr->ip || ipptr->ip1) {
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("%s,%s,",
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
unpack_ip_tostring(ipptr->ip1, options));
|
||||
}
|
||||
offset += sizeof(struct ipportip);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" --hashsize %u --probes %u --resize %u\n",
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (ipptr) {
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("-A %s %s,%s,", set->name,
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
unpack_ip_tostring(ipptr->ip, options));
|
||||
}
|
||||
offset += sizeof(struct ipportip);
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipportnethash --from IP --to IP\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-N set ipportnethash --network IP/mask\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-A set IP,port,IP/net\n"
|
||||
"-D set IP,port,IP/net\n"
|
||||
"-T set IP,port,IP[/net]\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipportnethash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipportnethash_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipportnethash),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipportnethash),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips, /* We only have the unsorted version */
|
||||
.printips_sorted = &printips,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipportnethash)
|
||||
{
|
||||
settype_register(&settype_ipportnethash);
|
||||
|
||||
}
|
@@ -15,36 +15,33 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_iptree.h"
|
||||
#include "ipset.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_TIMEOUT 0x01U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void create_init(void *data)
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_iptree_create *mydata =
|
||||
(struct ip_set_req_iptree_create *) data;
|
||||
struct ip_set_req_iptree_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
mydata->timeout = 0;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_iptree_create *mydata =
|
||||
(struct ip_set_req_iptree_create *) data;
|
||||
struct ip_set_req_iptree_create *mydata = data;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
@@ -65,27 +62,32 @@ static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void create_final(void *data, unsigned int flags)
|
||||
static void
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{"timeout", 1, 0, '1'},
|
||||
{.name = "timeout", .has_arg = required_argument, .val = '1'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_iptree *mydata =
|
||||
(struct ip_set_req_iptree *) data;
|
||||
struct ip_set_req_iptree *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("iptree: %p %p", arg, data);
|
||||
|
||||
ptr = strsep(&tmp, ":%");
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,timeout.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp)
|
||||
@@ -93,7 +95,7 @@ static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
else
|
||||
mydata->timeout = 0;
|
||||
|
||||
free(saved);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -101,38 +103,36 @@ static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void initheader(struct set *set, const void *data)
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
struct ip_set_req_iptree_create *header =
|
||||
(struct ip_set_req_iptree_create *) data;
|
||||
struct ip_set_iptree *map =
|
||||
(struct ip_set_iptree *) set->settype->header;
|
||||
const struct ip_set_req_iptree_create *header = data;
|
||||
struct ip_set_iptree *map = set->settype->header;
|
||||
|
||||
map->timeout = header->timeout;
|
||||
}
|
||||
|
||||
static void printheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata =
|
||||
(struct ip_set_iptree *) set->settype->header;
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
|
||||
if (mysetdata->timeout)
|
||||
printf(" timeout: %u", mysetdata->timeout);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void printips_sorted(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
printips_sorted(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata =
|
||||
(struct ip_set_iptree *) set->settype->header;
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
struct ip_set_req_iptree *req;
|
||||
size_t offset = 0;
|
||||
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptree)) {
|
||||
req = (struct ip_set_req_iptree *)(data + offset);
|
||||
if (mysetdata->timeout)
|
||||
printf("%s:%u\n", ip_tostring(req->ip, options),
|
||||
printf("%s,%u\n", ip_tostring(req->ip, options),
|
||||
req->timeout);
|
||||
else
|
||||
printf("%s\n", ip_tostring(req->ip, options));
|
||||
@@ -140,10 +140,10 @@ static void printips_sorted(struct set *set, void *data, size_t len,
|
||||
}
|
||||
}
|
||||
|
||||
static void saveheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata =
|
||||
(struct ip_set_iptree *) set->settype->header;
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
|
||||
if (mysetdata->timeout)
|
||||
printf("-N %s %s --timeout %u\n",
|
||||
@@ -154,11 +154,10 @@ static void saveheader(struct set *set, unsigned int options)
|
||||
set->name, set->settype->typename);
|
||||
}
|
||||
|
||||
static void saveips(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata =
|
||||
(struct ip_set_iptree *) set->settype->header;
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
struct ip_set_req_iptree *req;
|
||||
size_t offset = 0;
|
||||
|
||||
@@ -167,7 +166,7 @@ static void saveips(struct set *set, void *data, size_t len,
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptree)) {
|
||||
req = (struct ip_set_req_iptree *)(data + offset);
|
||||
if (mysetdata->timeout)
|
||||
printf("-A %s %s:%u\n",
|
||||
printf("-A %s %s,%u\n",
|
||||
set->name,
|
||||
ip_tostring(req->ip, options),
|
||||
req->timeout);
|
||||
@@ -183,7 +182,7 @@ static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set iptree [--timeout value]\n"
|
||||
"-A set IP[:timeout]\n"
|
||||
"-A set IP[,timeout]\n"
|
||||
"-D set IP\n"
|
||||
"-T set IP\n");
|
||||
}
|
||||
@@ -219,7 +218,7 @@ static struct settype settype_iptree = {
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void iptree_init(void)
|
||||
CONSTRUCTOR(iptree)
|
||||
{
|
||||
settype_register(&settype_iptree);
|
||||
|
||||
|
@@ -15,17 +15,14 @@
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "ip_set_iptreemap.h"
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_iptreemap.h"
|
||||
|
||||
#define OPT_CREATE_GC 0x1
|
||||
|
||||
static void
|
||||
@@ -37,7 +34,7 @@ create_init(void *data)
|
||||
}
|
||||
|
||||
static int
|
||||
create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned int *flags)
|
||||
{
|
||||
struct ip_set_req_iptreemap_create *mydata = data;
|
||||
|
||||
@@ -56,17 +53,17 @@ create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
}
|
||||
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct option create_opts[] = {
|
||||
{"gc", 1, 0, 'g'},
|
||||
{.name = "gc", .has_arg = required_argument, .val = 'g'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static ip_set_ip_t
|
||||
adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_iptreemap *mydata = data;
|
||||
ip_set_ip_t mask;
|
||||
@@ -75,19 +72,24 @@ adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
if (strchr(tmp, '/')) {
|
||||
parse_ipandmask(tmp, &mydata->start, &mask);
|
||||
mydata->end = mydata->start | ~mask;
|
||||
parse_ipandmask(tmp, &mydata->ip, &mask);
|
||||
mydata->end = mydata->ip | ~mask;
|
||||
} else {
|
||||
ptr = strsep(&tmp, ":");
|
||||
parse_ip(ptr, &mydata->start);
|
||||
if ((ptr = strchr(tmp, ':')) != NULL && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use '-' separator token between IP range.\n"
|
||||
"Next release won't support old separator token.\n");
|
||||
ptr = strsep(&tmp, "-:");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp) {
|
||||
parse_ip(tmp, &mydata->end);
|
||||
} else {
|
||||
mydata->end = mydata->start;
|
||||
mydata->end = mydata->ip;
|
||||
}
|
||||
}
|
||||
|
||||
ipset_free(saved);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -101,7 +103,7 @@ initheader(struct set *set, const void *data)
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned int options)
|
||||
printheader(struct set *set, unsigned int options UNUSED)
|
||||
{
|
||||
struct ip_set_iptreemap *mysetdata = set->settype->header;
|
||||
|
||||
@@ -112,7 +114,8 @@ printheader(struct set *set, unsigned int options)
|
||||
}
|
||||
|
||||
static void
|
||||
printips_sorted(struct set *set, void *data, size_t len, unsigned int options)
|
||||
printips_sorted(struct set *set UNUSED, void *data,
|
||||
size_t len, unsigned int options)
|
||||
{
|
||||
struct ip_set_req_iptreemap *req;
|
||||
size_t offset = 0;
|
||||
@@ -120,9 +123,9 @@ printips_sorted(struct set *set, void *data, size_t len, unsigned int options)
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
|
||||
req = data + offset;
|
||||
|
||||
printf("%s", ip_tostring(req->start, options));
|
||||
if (req->start != req->end)
|
||||
printf(":%s", ip_tostring(req->end, options));
|
||||
printf("%s", ip_tostring(req->ip, options));
|
||||
if (req->ip != req->end)
|
||||
printf("-%s", ip_tostring(req->end, options));
|
||||
printf("\n");
|
||||
|
||||
offset += sizeof(struct ip_set_req_iptreemap);
|
||||
@@ -130,7 +133,7 @@ printips_sorted(struct set *set, void *data, size_t len, unsigned int options)
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned int options)
|
||||
saveheader(struct set *set, unsigned int options UNUSED)
|
||||
{
|
||||
struct ip_set_iptreemap *mysetdata = set->settype->header;
|
||||
|
||||
@@ -143,7 +146,8 @@ saveheader(struct set *set, unsigned int options)
|
||||
}
|
||||
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len, unsigned int options)
|
||||
saveips(struct set *set UNUSED, void *data,
|
||||
size_t len, unsigned int options)
|
||||
{
|
||||
struct ip_set_req_iptreemap *req;
|
||||
size_t offset = 0;
|
||||
@@ -151,10 +155,10 @@ saveips(struct set *set, void *data, size_t len, unsigned int options)
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
|
||||
req = data + offset;
|
||||
|
||||
printf("-A %s %s", set->name, ip_tostring(req->start, options));
|
||||
printf("-A %s %s", set->name, ip_tostring(req->ip, options));
|
||||
|
||||
if (req->start != req->end)
|
||||
printf(":%s", ip_tostring(req->end, options));
|
||||
if (req->ip != req->end)
|
||||
printf("-%s", ip_tostring(req->end, options));
|
||||
|
||||
printf("\n");
|
||||
|
||||
@@ -200,7 +204,7 @@ static struct settype settype_iptreemap = {
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void iptreemap_init(void)
|
||||
CONSTRUCTOR(iptreemap)
|
||||
{
|
||||
settype_register(&settype_iptreemap);
|
||||
}
|
||||
|
@@ -18,16 +18,14 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <stdlib.h> /* mem* */
|
||||
#include <string.h> /* str* */
|
||||
#include <net/ethernet.h> /* ETH_ALEN */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_macipmap.h"
|
||||
#include "ipset.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
@@ -40,17 +38,18 @@
|
||||
#define OPT_ADDDEL_MAC 0x02U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void create_init(void *data)
|
||||
static void
|
||||
create_init(void *data UNUSED)
|
||||
{
|
||||
DP("create INIT");
|
||||
/* Nothing */
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_macipmap_create *mydata =
|
||||
(struct ip_set_req_macipmap_create *) data;
|
||||
struct ip_set_req_macipmap_create *mydata = data;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
@@ -107,10 +106,10 @@ static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void create_final(void *data, unsigned int flags)
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_macipmap_create *mydata =
|
||||
(struct ip_set_req_macipmap_create *) data;
|
||||
struct ip_set_req_macipmap_create *mydata = data;
|
||||
|
||||
if (flags == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
@@ -146,14 +145,15 @@ static void create_final(void *data, unsigned int flags)
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{"from", 1, 0, '1'},
|
||||
{"to", 1, 0, '2'},
|
||||
{"network", 1, 0, '3'},
|
||||
{"matchunset", 0, 0, '4'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "matchunset", .has_arg = no_argument, .val = '4'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void parse_mac(const char *mac, unsigned char *ethernet)
|
||||
static void
|
||||
parse_mac(const char *mac, unsigned char *ethernet)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
@@ -175,16 +175,23 @@ static void parse_mac(const char *mac, unsigned char *ethernet)
|
||||
}
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_macipmap *mydata =
|
||||
(struct ip_set_req_macipmap *) data;
|
||||
struct ip_set_req_macipmap *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("macipmap: %p %p", arg, data);
|
||||
|
||||
ptr = strsep(&tmp, ":%");
|
||||
ptr = strsep(&tmp, ",");
|
||||
if (!tmp) {
|
||||
tmp = saved;
|
||||
ptr = strsep(&tmp, ":%");
|
||||
if (tmp && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,mac.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
}
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp)
|
||||
@@ -193,6 +200,7 @@ static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
memset(mydata->ethernet, 0, ETH_ALEN);
|
||||
|
||||
free(saved);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -200,12 +208,11 @@ static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void initheader(struct set *set, const void *data)
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
struct ip_set_req_macipmap_create *header =
|
||||
(struct ip_set_req_macipmap_create *) data;
|
||||
struct ip_set_macipmap *map =
|
||||
(struct ip_set_macipmap *) set->settype->header;
|
||||
const struct ip_set_req_macipmap_create *header = data;
|
||||
struct ip_set_macipmap *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_macipmap));
|
||||
map->first_ip = header->from;
|
||||
@@ -213,10 +220,10 @@ static void initheader(struct set *set, const void *data)
|
||||
map->flags = header->flags;
|
||||
}
|
||||
|
||||
static void printheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata =
|
||||
(struct ip_set_macipmap *) set->settype->header;
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
@@ -226,7 +233,8 @@ static void printheader(struct set *set, unsigned int options)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void print_mac(unsigned char macaddress[ETH_ALEN])
|
||||
static void
|
||||
print_mac(unsigned char macaddress[ETH_ALEN])
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -235,19 +243,18 @@ static void print_mac(unsigned char macaddress[ETH_ALEN])
|
||||
printf(":%02X", macaddress[i]);
|
||||
}
|
||||
|
||||
static void printips_sorted(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
printips_sorted(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata =
|
||||
(struct ip_set_macipmap *) set->settype->header;
|
||||
struct ip_set_macip *table =
|
||||
(struct ip_set_macip *) data;
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
struct ip_set_macip *table = data;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (test_bit(IPSET_MACIP_ISSET,
|
||||
(void *)&table[addr - mysetdata->first_ip].flags)) {
|
||||
printf("%s:", ip_tostring(addr, options));
|
||||
printf("%s,", ip_tostring(addr, options));
|
||||
print_mac(table[addr - mysetdata->first_ip].
|
||||
ethernet);
|
||||
printf("\n");
|
||||
@@ -256,10 +263,10 @@ static void printips_sorted(struct set *set, void *data, size_t len,
|
||||
}
|
||||
}
|
||||
|
||||
static void saveheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata =
|
||||
(struct ip_set_macipmap *) set->settype->header;
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
@@ -271,19 +278,18 @@ static void saveheader(struct set *set, unsigned int options)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void saveips(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
saveips(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata =
|
||||
(struct ip_set_macipmap *) set->settype->header;
|
||||
struct ip_set_macip *table =
|
||||
(struct ip_set_macip *) data;
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
struct ip_set_macip *table = data;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (test_bit(IPSET_MACIP_ISSET,
|
||||
(void *)&table[addr - mysetdata->first_ip].flags)) {
|
||||
printf("-A %s %s:",
|
||||
printf("-A %s %s,",
|
||||
set->name, ip_tostring(addr, options));
|
||||
print_mac(table[addr - mysetdata->first_ip].
|
||||
ethernet);
|
||||
@@ -298,9 +304,9 @@ static void usage(void)
|
||||
printf
|
||||
("-N set macipmap --from IP --to IP [--matchunset]\n"
|
||||
"-N set macipmap --network IP/mask [--matchunset]\n"
|
||||
"-A set IP:MAC\n"
|
||||
"-D set IP[:MAC]\n"
|
||||
"-T set IP[:MAC]\n");
|
||||
"-A set IP[,MAC]\n"
|
||||
"-D set IP[,MAC]\n"
|
||||
"-T set IP[,MAC]\n");
|
||||
}
|
||||
|
||||
static struct settype settype_macipmap = {
|
||||
@@ -334,7 +340,7 @@ static struct settype settype_macipmap = {
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void macipmap_init(void)
|
||||
CONSTRUCTOR(macipmap)
|
||||
{
|
||||
settype_register(&settype_macipmap);
|
||||
|
||||
|
@@ -15,24 +15,14 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
#include "ip_set_nethash.h"
|
||||
#include "ip_set_jhash.h"
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_nethash.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
@@ -40,10 +30,10 @@
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void create_init(void *data)
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_nethash_create *mydata =
|
||||
(struct ip_set_req_nethash_create *) data;
|
||||
struct ip_set_req_nethash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
@@ -54,10 +44,10 @@ static void create_init(void *data)
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_nethash_create *mydata =
|
||||
(struct ip_set_req_nethash_create *) data;
|
||||
struct ip_set_req_nethash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
@@ -106,30 +96,24 @@ static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void create_final(void *data, unsigned int flags)
|
||||
static void
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
#ifdef IPSET_DEBUG
|
||||
struct ip_set_req_nethash_create *mydata =
|
||||
(struct ip_set_req_nethash_create *) data;
|
||||
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{"hashsize", 1, 0, '1'},
|
||||
{"probes", 1, 0, '2'},
|
||||
{"resize", 1, 0, '3'},
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_nethash *mydata =
|
||||
(struct ip_set_req_nethash *) data;
|
||||
struct ip_set_req_nethash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
ip_set_ip_t cidr;
|
||||
@@ -149,24 +133,25 @@ static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
|
||||
mydata->cidr = cidr;
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
#if 0
|
||||
if (!mydata->ip)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address `%s' specified", ptr);
|
||||
free(saved);
|
||||
#endif
|
||||
ipset_free(saved);
|
||||
|
||||
return mydata->ip;
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void initheader(struct set *set, const void *data)
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
struct ip_set_req_nethash_create *header =
|
||||
(struct ip_set_req_nethash_create *) data;
|
||||
struct ip_set_nethash *map =
|
||||
(struct ip_set_nethash *) set->settype->header;
|
||||
const struct ip_set_req_nethash_create *header = data;
|
||||
struct ip_set_nethash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_nethash));
|
||||
map->hashsize = header->hashsize;
|
||||
@@ -174,10 +159,10 @@ static void initheader(struct set *set, const void *data)
|
||||
map->resize = header->resize;
|
||||
}
|
||||
|
||||
static void printheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_nethash *mysetdata =
|
||||
(struct ip_set_nethash *) set->settype->header;
|
||||
struct ip_set_nethash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
@@ -186,7 +171,8 @@ static void printheader(struct set *set, unsigned int options)
|
||||
|
||||
static char buf[20];
|
||||
|
||||
static char * unpack_ip_tostring(ip_set_ip_t ip, unsigned options)
|
||||
static char *
|
||||
unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED)
|
||||
{
|
||||
int i, j = 3;
|
||||
unsigned char a, b;
|
||||
@@ -233,12 +219,12 @@ static char * unpack_ip_tostring(ip_set_ip_t ip, unsigned options)
|
||||
((unsigned char *)&ip)[3],
|
||||
b);
|
||||
|
||||
DP("%s %s", ip_tostring(ntohl(ip), options), buf);
|
||||
DP("%s %s", ip_tostring(ntohl(ip), 0), buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void printips(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
printips(struct set *set UNUSED, void *data, size_t len, unsigned options)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
@@ -251,10 +237,10 @@ static void printips(struct set *set, void *data, size_t len,
|
||||
}
|
||||
}
|
||||
|
||||
static void saveheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_nethash *mysetdata =
|
||||
(struct ip_set_nethash *) set->settype->header;
|
||||
struct ip_set_nethash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --hashsize %u --probes %u --resize %u\n",
|
||||
set->name, set->settype->typename,
|
||||
@@ -262,8 +248,8 @@ static void saveheader(struct set *set, unsigned int options)
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void saveips(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
saveips(struct set *set UNUSED, void *data, size_t len, unsigned options)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
@@ -277,14 +263,16 @@ static void saveips(struct set *set, void *data, size_t len,
|
||||
}
|
||||
}
|
||||
|
||||
static char * net_tostring(struct set *set, ip_set_ip_t ip, unsigned options)
|
||||
static char *
|
||||
net_tostring(struct set *set UNUSED, ip_set_ip_t ip, unsigned options)
|
||||
{
|
||||
return unpack_ip_tostring(ip, options);
|
||||
}
|
||||
|
||||
static void parse_net(const char *str, ip_set_ip_t *ip)
|
||||
static void
|
||||
parse_net(const char *str, ip_set_ip_t *ip)
|
||||
{
|
||||
char *saved = strdup(str);
|
||||
char *saved = ipset_strdup(str);
|
||||
char *ptr, *tmp = saved;
|
||||
ip_set_ip_t cidr;
|
||||
|
||||
@@ -299,9 +287,9 @@ static void parse_net(const char *str, ip_set_ip_t *ip)
|
||||
"Out of range cidr `%s' specified", str);
|
||||
|
||||
parse_ip(ptr, ip);
|
||||
free(saved);
|
||||
ipset_free(saved);
|
||||
|
||||
*ip = pack(*ip, cidr);
|
||||
*ip = pack_ip_cidr(*ip, cidr);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
@@ -345,7 +333,7 @@ static struct settype settype_nethash = {
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void nethash_init(void)
|
||||
CONSTRUCTOR(nethash)
|
||||
{
|
||||
settype_register(&settype_nethash);
|
||||
|
||||
|
@@ -16,15 +16,12 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ip_set_portmap.h"
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_portmap.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
@@ -34,17 +31,18 @@
|
||||
#define OPT_ADDDEL_PORT 0x01U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void create_init(void *data)
|
||||
static void
|
||||
create_init(void *data UNUSED)
|
||||
{
|
||||
DP("create INIT");
|
||||
/* Nothing */
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_portmap_create *mydata =
|
||||
(struct ip_set_req_portmap_create *) data;
|
||||
struct ip_set_req_portmap_create *mydata = data;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
@@ -77,10 +75,10 @@ static int create_parse(int c, char *argv[], void *data, unsigned int *flags)
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void create_final(void *data, unsigned int flags)
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_portmap_create *mydata =
|
||||
(struct ip_set_req_portmap_create *) data;
|
||||
struct ip_set_req_portmap_create *mydata = data;
|
||||
|
||||
if (flags == 0) {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
@@ -108,19 +106,19 @@ static void create_final(void *data, unsigned int flags)
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{"from", 1, 0, '1'},
|
||||
{"to", 1, 0, '2'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '2'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_portmap *mydata =
|
||||
(struct ip_set_req_portmap *) data;
|
||||
struct ip_set_req_portmap *mydata = data;
|
||||
|
||||
parse_port(arg, &mydata->port);
|
||||
DP("%s", port_tostring(mydata->port, 0));
|
||||
parse_port(arg, &mydata->ip);
|
||||
DP("%s", port_tostring(mydata->ip, 0));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -129,70 +127,70 @@ static ip_set_ip_t adt_parser(unsigned int cmd, const char *arg, void *data)
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void initheader(struct set *set, const void *data)
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
struct ip_set_req_portmap_create *header =
|
||||
(struct ip_set_req_portmap_create *) data;
|
||||
struct ip_set_portmap *map =
|
||||
(struct ip_set_portmap *) set->settype->header;
|
||||
const struct ip_set_req_portmap_create *header = data;
|
||||
struct ip_set_portmap *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_portmap));
|
||||
map->first_port = header->from;
|
||||
map->last_port = header->to;
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void printheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata =
|
||||
(struct ip_set_portmap *) set->settype->header;
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", port_tostring(mysetdata->first_port, options));
|
||||
printf(" to: %s\n", port_tostring(mysetdata->last_port, options));
|
||||
printf(" from: %s", port_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s\n", port_tostring(mysetdata->last_ip, options));
|
||||
}
|
||||
|
||||
static void printports_sorted(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
printports_sorted(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata =
|
||||
(struct ip_set_portmap *) set->settype->header;
|
||||
u_int32_t addr = mysetdata->first_port;
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
DP("%u -- %u", mysetdata->first_port, mysetdata->last_port);
|
||||
while (addr <= mysetdata->last_port) {
|
||||
if (test_bit(addr - mysetdata->first_port, data))
|
||||
DP("%u -- %u", mysetdata->first_ip, mysetdata->last_ip);
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (test_bit(addr - mysetdata->first_ip, data))
|
||||
printf("%s\n", port_tostring(addr, options));
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
static char *binding_port_tostring(struct set *set, ip_set_ip_t ip,
|
||||
unsigned int options)
|
||||
static char *
|
||||
binding_port_tostring(struct set *set UNUSED,
|
||||
ip_set_ip_t ip, unsigned options)
|
||||
{
|
||||
return port_tostring(ip, options);
|
||||
}
|
||||
|
||||
static void saveheader(struct set *set, unsigned int options)
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata =
|
||||
(struct ip_set_portmap *) set->settype->header;
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name,
|
||||
set->settype->typename,
|
||||
port_tostring(mysetdata->first_port, options));
|
||||
port_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s\n",
|
||||
port_tostring(mysetdata->last_port, options));
|
||||
port_tostring(mysetdata->last_ip, options));
|
||||
}
|
||||
|
||||
static void saveports(struct set *set, void *data, size_t len,
|
||||
unsigned int options)
|
||||
static void
|
||||
saveports(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata =
|
||||
(struct ip_set_portmap *) set->settype->header;
|
||||
u_int32_t addr = mysetdata->first_port;
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
while (addr <= mysetdata->last_port) {
|
||||
if (test_bit(addr - mysetdata->first_port, data))
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (test_bit(addr - mysetdata->first_ip, data))
|
||||
printf("-A %s %s\n",
|
||||
set->name,
|
||||
port_tostring(addr, options));
|
||||
@@ -240,7 +238,7 @@ static struct settype settype_portmap = {
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void portmap_init(void)
|
||||
CONSTRUCTOR(portmap)
|
||||
{
|
||||
settype_register(&settype_portmap);
|
||||
|
||||
|
221
extensions/ipset/ipset_setlist.c
Normal file
221
extensions/ipset/ipset_setlist.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/* Copyright 2008 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 as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "ip_set_setlist.h"
|
||||
#include "ipset.h"
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_setlist_create *mydata = data;
|
||||
|
||||
mydata->size = 8;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags UNUSED)
|
||||
{
|
||||
struct ip_set_req_setlist_create *mydata = data;
|
||||
unsigned int size;
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
if (string_to_number(optarg, 1, 255, &size))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid size '%s specified: must be "
|
||||
"between 1-255", optarg);
|
||||
mydata->size = size;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "size", .has_arg = required_argument, .val = '1'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void check_setname(const char *name)
|
||||
{
|
||||
if (strlen(name) > IP_SET_MAXNAMELEN - 1)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Setname %s is longer than %d characters.",
|
||||
name, IP_SET_MAXNAMELEN - 1);
|
||||
}
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_setlist *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("setlist: %p %p", arg, data);
|
||||
|
||||
ptr = strsep(&tmp, ",");
|
||||
check_setname(ptr);
|
||||
strcpy(mydata->name, ptr);
|
||||
|
||||
if (!tmp) {
|
||||
mydata->before = 0;
|
||||
mydata->ref[0] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr = strsep(&tmp, ",");
|
||||
|
||||
if (tmp == NULL || !(strcmp(ptr, "before") == 0 || strcmp(ptr, "after") == 0))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Syntax error, you must specify elements as setname,[before|after],setname");
|
||||
|
||||
check_setname(tmp);
|
||||
strcpy(mydata->ref, tmp);
|
||||
mydata->before = !strcmp(ptr, "before");
|
||||
|
||||
free(saved);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_setlist_create *header = data;
|
||||
struct ip_set_setlist *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_setlist));
|
||||
map->size = header->size;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
|
||||
printf(" size: %u\n", mysetdata->size);
|
||||
}
|
||||
|
||||
static void
|
||||
printips_sorted(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
int i;
|
||||
ip_set_id_t id;
|
||||
struct set *elem;
|
||||
|
||||
for (i = 0; i < mysetdata->size; i++ ) {
|
||||
id = *((ip_set_id_t *)data + i);
|
||||
if (id == IP_SET_INVALID_ID)
|
||||
return;
|
||||
elem = set_find_byid(id);
|
||||
printf("%s\n", elem->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --size %u\n",
|
||||
set->name, set->settype->typename,
|
||||
mysetdata->size);
|
||||
}
|
||||
|
||||
static void
|
||||
saveips(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
int i;
|
||||
ip_set_id_t id;
|
||||
struct set *elem;
|
||||
|
||||
for (i = 0; i < mysetdata->size; i++ ) {
|
||||
id = *((ip_set_id_t *)data + i);
|
||||
if (id == IP_SET_INVALID_ID)
|
||||
return;
|
||||
elem = set_find_byid(id);
|
||||
printf("-A %s %s\n", set->name, elem->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set setlist --size size\n"
|
||||
"-A set setname[,before|after,setname]\n"
|
||||
"-D set setname\n"
|
||||
"-T set setname\n");
|
||||
}
|
||||
|
||||
static struct settype settype_setlist = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_setlist_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_setlist),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_setlist),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips_sorted, /* We only have sorted version */
|
||||
.printips_sorted = &printips_sorted,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(setlist)
|
||||
{
|
||||
settype_register(&settype_setlist);
|
||||
|
||||
}
|
@@ -10,82 +10,48 @@
|
||||
|
||||
/* ipt_SET.c - netfilter target to manipulate IP sets */
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/protocol.h>
|
||||
#include <net/checksum.h>
|
||||
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#define xt_register_target ipt_register_target
|
||||
#define xt_unregister_target ipt_unregister_target
|
||||
#define xt_target ipt_target
|
||||
#define XT_CONTINUE IPT_CONTINUE
|
||||
#else
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#endif
|
||||
#include "ipt_set.h"
|
||||
#include "../compat_xtables.h"
|
||||
|
||||
static unsigned int
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
|
||||
target(struct sk_buff *skb,
|
||||
#else
|
||||
target(struct sk_buff **pskb,
|
||||
#endif
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
unsigned int hooknum,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
|
||||
const struct xt_target *target,
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
const void *targinfo,
|
||||
void *userinfo)
|
||||
#else
|
||||
const void *targinfo)
|
||||
#endif
|
||||
target(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct ipt_set_info_target *info = targinfo;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
|
||||
struct sk_buff *skb = *pskb;
|
||||
#endif
|
||||
const struct ipt_set_info_target *info = par->targinfo;
|
||||
|
||||
|
||||
if (info->add_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_addip_kernel(info->add_set.index,
|
||||
skb,
|
||||
*pskb,
|
||||
info->add_set.flags);
|
||||
if (info->del_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_delip_kernel(info->del_set.index,
|
||||
skb,
|
||||
*pskb,
|
||||
info->del_set.flags);
|
||||
|
||||
return IPT_CONTINUE;
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
#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 *e,
|
||||
#else
|
||||
const struct ipt_entry *e,
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
|
||||
const struct xt_target *target,
|
||||
#endif
|
||||
void *targinfo,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
unsigned int targinfosize,
|
||||
#endif
|
||||
unsigned int hook_mask)
|
||||
checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
struct ipt_set_info_target *info = targinfo;
|
||||
struct ipt_set_info_target *info = par->targinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (targinfosize != IPT_ALIGN(sizeof(*info))) {
|
||||
DP("bad target info size %u", targinfosize);
|
||||
return 0;
|
||||
@@ -118,61 +84,54 @@ checkentry(const char *tablename,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void destroy(
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
|
||||
const struct xt_target *target,
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
void *targetinfo, unsigned int targetsize)
|
||||
#else
|
||||
void *targetinfo)
|
||||
#endif
|
||||
static void destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
struct ipt_set_info_target *info = targetinfo;
|
||||
struct ipt_set_info_target *info = par->targinfo;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
|
||||
ip_set_printk("invalid targetsize %d", targetsize);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (info->add_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_put(info->add_set.index);
|
||||
ip_set_put_byindex(info->add_set.index);
|
||||
if (info->del_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_put(info->del_set.index);
|
||||
ip_set_put_byindex(info->del_set.index);
|
||||
}
|
||||
|
||||
static struct ipt_target SET_target = {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
static struct xt_target SET_target = {
|
||||
.name = "SET",
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
|
||||
.family = AF_INET,
|
||||
#endif
|
||||
.target = target,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
|
||||
.targetsize = sizeof(struct ipt_set_info_target),
|
||||
#endif
|
||||
.checkentry = checkentry,
|
||||
.destroy = destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) */
|
||||
static struct xt_target SET_target = {
|
||||
.name = "SET",
|
||||
.family = AF_INET,
|
||||
.target = target,
|
||||
.targetsize = sizeof(struct ipt_set_info_target),
|
||||
.checkentry = checkentry,
|
||||
.destroy = destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("iptables IP set target module");
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
|
||||
#define ipt_register_target xt_register_target
|
||||
#define ipt_unregister_target xt_unregister_target
|
||||
#endif
|
||||
|
||||
static int __init ipt_SET_init(void)
|
||||
{
|
||||
return ipt_register_target(&SET_target);
|
||||
return xt_register_target(&SET_target);
|
||||
}
|
||||
|
||||
static void __exit ipt_SET_fini(void)
|
||||
{
|
||||
ipt_unregister_target(&SET_target);
|
||||
xt_unregister_target(&SET_target);
|
||||
}
|
||||
|
||||
module_init(ipt_SET_init);
|
||||
|
@@ -15,9 +15,17 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#define xt_register_match ipt_register_match
|
||||
#define xt_unregister_match ipt_unregister_match
|
||||
#define xt_match ipt_match
|
||||
#else
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#endif
|
||||
#include "ip_set.h"
|
||||
#include "ipt_set.h"
|
||||
#include "../compat_xtables.h"
|
||||
|
||||
static inline int
|
||||
match_set(const struct ipt_set_info *info,
|
||||
@@ -29,57 +37,23 @@ match_set(const struct ipt_set_info *info,
|
||||
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
|
||||
match(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct ipt_set_info_match *info = matchinfo;
|
||||
const struct ipt_set_info_match *info = par->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)
|
||||
checkentry(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct ipt_set_info_match *info = matchinfo;
|
||||
struct ipt_set_info_match *info = par->matchinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
|
||||
ip_set_printk("invalid matchsize %d", matchsize);
|
||||
return 0;
|
||||
@@ -101,58 +75,51 @@ checkentry(const char *tablename,
|
||||
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
|
||||
static void destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
struct ipt_set_info_match *info = matchinfo;
|
||||
struct ipt_set_info_match *info = par->matchinfo;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
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);
|
||||
ip_set_put_byindex(info->match_set.index);
|
||||
}
|
||||
|
||||
static struct ipt_match set_match = {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
static struct xt_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
|
||||
};
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) */
|
||||
static struct xt_match set_match = {
|
||||
.name = "set",
|
||||
.family = AF_INET,
|
||||
.match = &match,
|
||||
.matchsize = sizeof(struct ipt_set_info_match),
|
||||
.checkentry = &checkentry,
|
||||
.destroy = &destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#endif
|
||||
|
||||
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);
|
||||
return xt_register_match(&set_match);
|
||||
}
|
||||
|
||||
static void __exit ipt_ipset_fini(void)
|
||||
{
|
||||
ipt_unregister_match(&set_match);
|
||||
xt_unregister_match(&set_match);
|
||||
}
|
||||
|
||||
module_init(ipt_ipset_init);
|
||||
|
@@ -25,7 +25,7 @@ enum {
|
||||
static const struct option chaos_tg_opts[] = {
|
||||
{.name = "delude", .has_arg = false, .val = 'd'},
|
||||
{.name = "tarpit", .has_arg = false, .val = 't'},
|
||||
{},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void chaos_tg_help(void)
|
||||
|
@@ -22,7 +22,7 @@ enum {
|
||||
static const struct option logmark_tg_opts[] = {
|
||||
{.name = "log-level", .has_arg = true, .val = 'l'},
|
||||
{.name = "log-prefix", .has_arg = true, .val = 'p'},
|
||||
{},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void logmark_tg_help(void)
|
||||
|
@@ -30,7 +30,7 @@ enum {
|
||||
|
||||
static const struct option tee_tg_opts[] = {
|
||||
{.name = "gateway", .has_arg = true, .val = 'g'},
|
||||
{},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void tee_tg_help(void)
|
||||
|
@@ -23,7 +23,7 @@ static const struct option portscan_mt_opts[] = {
|
||||
{.name = "synscan", .has_arg = false, .val = 's'},
|
||||
{.name = "cnscan", .has_arg = false, .val = 'c'},
|
||||
{.name = "grscan", .has_arg = false, .val = 'g'},
|
||||
{},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void portscan_mt_help(void)
|
||||
|
@@ -44,13 +44,13 @@ static const struct xt_tcp tcp_params = {
|
||||
};
|
||||
|
||||
/* CHAOS functions */
|
||||
static void xt_chaos_total(const struct xt_chaos_tginfo *info,
|
||||
struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum)
|
||||
static void
|
||||
xt_chaos_total(struct sk_buff *skb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_chaos_tginfo *info = par->targinfo;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
const int protoff = 4 * iph->ihl;
|
||||
const int offset = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
const int thoff = 4 * iph->ihl;
|
||||
const int fragoff = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
typeof(xt_tarpit) destiny;
|
||||
bool ret;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
@@ -59,24 +59,44 @@ static void xt_chaos_total(const struct xt_chaos_tginfo *info,
|
||||
bool hotdrop = false;
|
||||
#endif
|
||||
|
||||
ret = xm_tcp->match(skb, in, out, xm_tcp, &tcp_params,
|
||||
offset, protoff, &hotdrop);
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
ret = xm_tcp->match(skb, par->in, par->out, xm_tcp, &tcp_params,
|
||||
fragoff, thoff, &hotdrop);
|
||||
#else
|
||||
{
|
||||
struct xt_match_param local_par = {
|
||||
.in = par->in,
|
||||
.out = par->out,
|
||||
.match = xm_tcp,
|
||||
.matchinfo = &tcp_params,
|
||||
.fragoff = fragoff,
|
||||
.thoff = thoff,
|
||||
.hotdrop = &hotdrop,
|
||||
};
|
||||
ret = xm_tcp->match(skb, &local_par);
|
||||
}
|
||||
#endif
|
||||
if (!ret || hotdrop || (unsigned int)net_random() > delude_percentage)
|
||||
return;
|
||||
|
||||
destiny = (info->variant == XTCHAOS_TARPIT) ? xt_tarpit : xt_delude;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
destiny->target(&skb, in, out, hooknum, destiny, NULL, NULL);
|
||||
destiny->target(&skb, par->in, par->out, par->hooknum, destiny, NULL, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
destiny->target(&skb, in, out, hooknum, destiny, NULL);
|
||||
destiny->target(&skb, par->in, par->out, par->hooknum, destiny, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
destiny->target(skb, par->in, par->out, par->hooknum, destiny, NULL);
|
||||
#else
|
||||
destiny->target(skb, in, out, hooknum, destiny, NULL);
|
||||
{
|
||||
struct xt_target_param local_par = *par;
|
||||
local_par.target = destiny;
|
||||
destiny->target(skb, &local_par);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned int chaos_tg(struct sk_buff **pskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *target, const void *targinfo)
|
||||
static unsigned int
|
||||
chaos_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
/*
|
||||
* Equivalent to:
|
||||
@@ -86,34 +106,44 @@ static unsigned int chaos_tg(struct sk_buff **pskb,
|
||||
* $delude_percentage -j DELUDE;
|
||||
* -A chaos -j DROP;
|
||||
*/
|
||||
const struct xt_chaos_tginfo *info = targinfo;
|
||||
const struct xt_chaos_tginfo *info = par->targinfo;
|
||||
struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
|
||||
if ((unsigned int)net_random() <= reject_percentage)
|
||||
if ((unsigned int)net_random() <= reject_percentage) {
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
return xt_reject->target(pskb, in, out, hooknum,
|
||||
target->__compat_target, &reject_params, NULL);
|
||||
return xt_reject->target(pskb, par->in, par->out, par->hooknum,
|
||||
xt_reject, &reject_params, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return xt_reject->target(pskb, in, out, hooknum,
|
||||
target->__compat_target, &reject_params);
|
||||
return xt_reject->target(pskb, par->in, par->out, par->hooknum,
|
||||
xt_reject, &reject_params);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
return xt_reject->target(skb, par->in, par->out, par->hooknum,
|
||||
xt_reject, &reject_params);
|
||||
#else
|
||||
return xt_reject->target(skb, in, out, hooknum,
|
||||
target->__compat_target, &reject_params);
|
||||
struct xt_target_param local_par = {
|
||||
.in = par->in,
|
||||
.out = par->out,
|
||||
.hooknum = par->hooknum,
|
||||
.target = xt_reject,
|
||||
.targinfo = &reject_params,
|
||||
};
|
||||
return xt_reject->target(skb, &local_par);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TARPIT/DELUDE may not be called from the OUTPUT chain */
|
||||
if (iph->protocol == IPPROTO_TCP &&
|
||||
info->variant != XTCHAOS_NORMAL && hooknum != NF_INET_LOCAL_OUT)
|
||||
xt_chaos_total(info, skb, in, out, hooknum);
|
||||
info->variant != XTCHAOS_NORMAL &&
|
||||
par->hooknum != NF_INET_LOCAL_OUT)
|
||||
xt_chaos_total(skb, par);
|
||||
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
static bool chaos_tg_check(const char *tablename, const void *entry,
|
||||
const struct xt_target *target, void *targinfo, unsigned int hook_mask)
|
||||
static bool chaos_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_chaos_tginfo *info = targinfo;
|
||||
const struct xt_chaos_tginfo *info = par->targinfo;
|
||||
|
||||
if (info->variant == XTCHAOS_DELUDE && !have_delude) {
|
||||
printk(KERN_WARNING PFX "Error: Cannot use --delude when "
|
||||
@@ -131,7 +161,8 @@ static bool chaos_tg_check(const char *tablename, const void *entry,
|
||||
|
||||
static struct xt_target chaos_tg_reg = {
|
||||
.name = "CHAOS",
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "filter",
|
||||
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) |
|
||||
(1 << NF_INET_LOCAL_OUT),
|
||||
@@ -145,27 +176,27 @@ static int __init chaos_tg_init(void)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
xm_tcp = xt_request_find_match(AF_INET, "tcp", 0);
|
||||
xm_tcp = xt_request_find_match(NFPROTO_IPV4, "tcp", 0);
|
||||
if (xm_tcp == NULL) {
|
||||
printk(KERN_WARNING PFX "Error: Could not find or load "
|
||||
"\"tcp\" match\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
xt_reject = xt_request_find_target(AF_INET, "REJECT", 0);
|
||||
xt_reject = xt_request_find_target(NFPROTO_IPV4, "REJECT", 0);
|
||||
if (xt_reject == NULL) {
|
||||
printk(KERN_WARNING PFX "Error: Could not find or load "
|
||||
"\"REJECT\" target\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
xt_tarpit = xt_request_find_target(AF_INET, "TARPIT", 0);
|
||||
xt_tarpit = xt_request_find_target(NFPROTO_IPV4, "TARPIT", 0);
|
||||
have_tarpit = xt_tarpit != NULL;
|
||||
if (!have_tarpit)
|
||||
printk(KERN_WARNING PFX "Warning: Could not find or load "
|
||||
"\"TARPIT\" target\n");
|
||||
|
||||
xt_delude = xt_request_find_target(AF_INET, "DELUDE", 0);
|
||||
xt_delude = xt_request_find_target(NFPROTO_IPV4, "DELUDE", 0);
|
||||
have_delude = xt_delude != NULL;
|
||||
if (!have_delude)
|
||||
printk(KERN_WARNING PFX "Warning: Could not find or load "
|
||||
|
@@ -143,21 +143,20 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
kfree_skb(nskb);
|
||||
}
|
||||
|
||||
static unsigned int delude_tg(struct sk_buff **pskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *target, const void *targinfo)
|
||||
static unsigned int
|
||||
delude_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
/* WARNING: This code causes reentry within iptables.
|
||||
This means that the iptables jump stack is now crap. We
|
||||
must return an absolute verdict. --RR */
|
||||
delude_send_reset(*pskb, hooknum);
|
||||
delude_send_reset(*pskb, par->hooknum);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
static struct xt_target delude_tg_reg __read_mostly = {
|
||||
.name = "DELUDE",
|
||||
.revision = 0,
|
||||
.family = AF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "filter",
|
||||
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
|
||||
.proto = IPPROTO_TCP,
|
||||
|
@@ -68,15 +68,14 @@ static bool ether_cmp(const unsigned char *lh, const unsigned char *rh,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dhcpaddr_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, const struct xt_match *match,
|
||||
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
|
||||
static bool
|
||||
dhcpaddr_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct dhcpaddr_info *info = matchinfo;
|
||||
const struct dhcpaddr_info *info = par->matchinfo;
|
||||
const struct dhcp_message *dh;
|
||||
struct dhcp_message dhcpbuf;
|
||||
|
||||
dh = skb_header_pointer(skb, protoff + sizeof(struct udphdr),
|
||||
dh = skb_header_pointer(skb, par->thoff + sizeof(struct udphdr),
|
||||
sizeof(dhcpbuf), &dhcpbuf);
|
||||
if (dh == NULL)
|
||||
/*
|
||||
@@ -89,11 +88,10 @@ static bool dhcpaddr_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
return ether_cmp((const void *)dh->chaddr, info->addr, info->mask);
|
||||
}
|
||||
|
||||
static unsigned int dhcpaddr_tg(struct sk_buff **pskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *target, const void *targinfo)
|
||||
static unsigned int
|
||||
dhcpaddr_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct dhcpaddr_info *info = targinfo;
|
||||
const struct dhcpaddr_info *info = par->targinfo;
|
||||
struct dhcp_message dhcpbuf, *dh;
|
||||
struct udphdr udpbuf, *udph;
|
||||
struct sk_buff *skb = *pskb;
|
||||
@@ -127,7 +125,7 @@ static unsigned int dhcpaddr_tg(struct sk_buff **pskb,
|
||||
static struct xt_target dhcpaddr_tg_reg __read_mostly = {
|
||||
.name = "DHCPADDR",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.proto = IPPROTO_UDP,
|
||||
.table = "mangle",
|
||||
.target = dhcpaddr_tg,
|
||||
@@ -138,7 +136,7 @@ static struct xt_target dhcpaddr_tg_reg __read_mostly = {
|
||||
static struct xt_match dhcpaddr_mt_reg __read_mostly = {
|
||||
.name = "dhcpaddr",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.proto = IPPROTO_UDP,
|
||||
.match = dhcpaddr_mt,
|
||||
.matchsize = XT_ALIGN(sizeof(struct dhcpaddr_info)),
|
||||
|
@@ -20,9 +20,8 @@
|
||||
#include <net/ip.h>
|
||||
#include "compat_xtables.h"
|
||||
|
||||
static unsigned int echo_tg4(struct sk_buff **poldskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *target, const void *targinfo)
|
||||
static unsigned int
|
||||
echo_tg4(struct sk_buff **poldskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct sk_buff *oldskb = *poldskb;
|
||||
const struct udphdr *oldudp;
|
||||
@@ -34,7 +33,7 @@ static unsigned int echo_tg4(struct sk_buff **poldskb,
|
||||
void *payload;
|
||||
|
||||
/* This allows us to do the copy operation in fewer lines of code. */
|
||||
if (skb_linearize(oldskb) < 0)
|
||||
if (skb_linearize(*poldskb) < 0)
|
||||
return NF_DROP;
|
||||
|
||||
oldip = ip_hdr(oldskb);
|
||||
@@ -87,7 +86,7 @@ static unsigned int echo_tg4(struct sk_buff **poldskb,
|
||||
dst_hold(oldskb->dst);
|
||||
newskb->dst = oldskb->dst;
|
||||
|
||||
if (ip_route_me_harder(newskb, addr_type) < 0)
|
||||
if (ip_route_me_harder(&newskb, addr_type) < 0)
|
||||
goto free_nskb;
|
||||
|
||||
newip->ttl = dst_metric(newskb->dst, RTAX_HOPLIMIT);
|
||||
@@ -97,7 +96,7 @@ static unsigned int echo_tg4(struct sk_buff **poldskb,
|
||||
if (newskb->len > dst_mtu(newskb->dst))
|
||||
goto free_nskb;
|
||||
|
||||
nf_ct_attach(newskb, oldskb);
|
||||
nf_ct_attach(newskb, *poldskb);
|
||||
ip_local_out(newskb);
|
||||
return NF_DROP;
|
||||
|
||||
@@ -109,7 +108,7 @@ static unsigned int echo_tg4(struct sk_buff **poldskb,
|
||||
static struct xt_target echo_tg_reg __read_mostly = {
|
||||
.name = "ECHO",
|
||||
.revision = 0,
|
||||
.family = AF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.proto = IPPROTO_UDP,
|
||||
.table = "filter",
|
||||
.target = echo_tg4,
|
||||
@@ -129,7 +128,7 @@ static void __exit echo_tg_exit(void)
|
||||
|
||||
module_init(echo_tg_init);
|
||||
module_exit(echo_tg_exit);
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_DESCRIPTION("Xtables: ECHO diagnosis target");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_ECHO");
|
||||
|
@@ -25,11 +25,9 @@ MODULE_ALIAS("ipt_IPMARK");
|
||||
MODULE_ALIAS("ip6t_IPMARK");
|
||||
|
||||
static unsigned int
|
||||
ipmark_tg4(struct sk_buff **pskb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
ipmark_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_ipmark_tginfo *ipmarkinfo = targinfo;
|
||||
const struct xt_ipmark_tginfo *ipmarkinfo = par->targinfo;
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
__u32 mark;
|
||||
@@ -63,11 +61,9 @@ static __u32 ipmark_from_ip6(const struct in6_addr *a, unsigned int s)
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
ipmark_tg6(struct sk_buff **pskb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
ipmark_tg6(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_ipmark_tginfo *info = targinfo;
|
||||
const struct xt_ipmark_tginfo *info = par->targinfo;
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
__u32 mark;
|
||||
@@ -87,7 +83,7 @@ static struct xt_target ipmark_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "IPMARK",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "mangle",
|
||||
.target = ipmark_tg4,
|
||||
.targetsize = XT_ALIGN(sizeof(struct xt_ipmark_tginfo)),
|
||||
@@ -96,7 +92,7 @@ static struct xt_target ipmark_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "IPMARK",
|
||||
.revision = 0,
|
||||
.family = PF_INET6,
|
||||
.family = NFPROTO_IPV6,
|
||||
.table = "mangle",
|
||||
.target = ipmark_tg6,
|
||||
.targetsize = XT_ALIGN(sizeof(struct xt_ipmark_tginfo)),
|
||||
|
@@ -30,19 +30,17 @@ static const char *const dir_names[] = {
|
||||
};
|
||||
|
||||
static unsigned int
|
||||
logmark_tg(struct sk_buff **pskb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
logmark_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct xt_logmark_tginfo *info = targinfo;
|
||||
const struct xt_logmark_tginfo *info = par->targinfo;
|
||||
const struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
bool prev = false;
|
||||
|
||||
printk("<%u>%.*s""hook=%s nfmark=0x%x secmark=0x%x classify=0x%x",
|
||||
info->level, (unsigned int)sizeof(info->prefix), info->prefix,
|
||||
hook_names[hooknum],
|
||||
hook_names[par->hooknum],
|
||||
skb_nfmark(skb), skb_secmark(skb), skb->priority);
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
@@ -83,11 +81,9 @@ logmark_tg(struct sk_buff **pskb, const struct net_device *in,
|
||||
}
|
||||
|
||||
static bool
|
||||
logmark_tg_check(const char *tablename, const void *e,
|
||||
const struct xt_target *target, void *targinfo,
|
||||
unsigned int hook_mask)
|
||||
logmark_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_logmark_tginfo *info = targinfo;
|
||||
const struct xt_logmark_tginfo *info = par->targinfo;
|
||||
|
||||
if (info->level >= 8) {
|
||||
pr_debug("LOGMARK: level %u >= 8\n", info->level);
|
||||
@@ -101,7 +97,7 @@ static struct xt_target logmark_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "LOGMARK",
|
||||
.revision = 0,
|
||||
.family = AF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.checkentry = logmark_tg_check,
|
||||
.target = logmark_tg,
|
||||
.targetsize = sizeof(struct xt_logmark_tginfo),
|
||||
@@ -110,7 +106,7 @@ static struct xt_target logmark_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "LOGMARK",
|
||||
.revision = 0,
|
||||
.family = AF_INET6,
|
||||
.family = NFPROTO_IPV6,
|
||||
.checkentry = logmark_tg_check,
|
||||
.target = logmark_tg,
|
||||
.targetsize = sizeof(struct xt_logmark_tginfo),
|
||||
|
@@ -58,9 +58,8 @@ static unsigned int sysrq_tg(const void *pdata, uint16_t len)
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
static unsigned int sysrq_tg4(struct sk_buff **pskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *target, const void *targinfo)
|
||||
static unsigned int
|
||||
sysrq_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph;
|
||||
@@ -80,9 +79,8 @@ static unsigned int sysrq_tg4(struct sk_buff **pskb,
|
||||
return sysrq_tg((void *)udph + sizeof(struct udphdr), len);
|
||||
}
|
||||
|
||||
static unsigned int sysrq_tg6(struct sk_buff **pskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *target, const void *targinfo)
|
||||
static unsigned int
|
||||
sysrq_tg6(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
struct sk_buff *skb = *pskb;
|
||||
const struct ipv6hdr *iph;
|
||||
@@ -102,18 +100,17 @@ static unsigned int sysrq_tg6(struct sk_buff **pskb,
|
||||
return sysrq_tg(udph + sizeof(struct udphdr), len);
|
||||
}
|
||||
|
||||
static bool sysrq_tg_check(const char *table, const void *ventry,
|
||||
const struct xt_target *target, void *targinfo, unsigned int hook_mask)
|
||||
static bool sysrq_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
if (target->family == PF_INET) {
|
||||
const struct ipt_entry *entry = ventry;
|
||||
if (par->target->family == NFPROTO_IPV4) {
|
||||
const struct ipt_entry *entry = par->entryinfo;
|
||||
|
||||
if ((entry->ip.proto != IPPROTO_UDP &&
|
||||
entry->ip.proto != IPPROTO_UDPLITE) ||
|
||||
entry->ip.invflags & XT_INV_PROTO)
|
||||
goto out;
|
||||
} else if (target->family == PF_INET6) {
|
||||
const struct ip6t_entry *entry = ventry;
|
||||
} else if (par->target->family == NFPROTO_IPV6) {
|
||||
const struct ip6t_entry *entry = par->entryinfo;
|
||||
|
||||
if ((entry->ipv6.proto != IPPROTO_UDP &&
|
||||
entry->ipv6.proto != IPPROTO_UDPLITE) ||
|
||||
@@ -131,16 +128,16 @@ static bool sysrq_tg_check(const char *table, const void *ventry,
|
||||
static struct xt_target sysrq_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "SYSRQ",
|
||||
.family = PF_INET,
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.target = sysrq_tg4,
|
||||
.checkentry = sysrq_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "SYSRQ",
|
||||
.family = PF_INET6,
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV6,
|
||||
.target = sysrq_tg6,
|
||||
.checkentry = sysrq_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
|
@@ -52,7 +52,7 @@
|
||||
static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook)
|
||||
{
|
||||
struct tcphdr _otcph, *oth, *tcph;
|
||||
unsigned int addr_type;
|
||||
unsigned int addr_type = RTN_UNSPEC;
|
||||
struct sk_buff *nskb;
|
||||
struct iphdr *niph;
|
||||
u_int16_t tmp;
|
||||
@@ -96,9 +96,11 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook)
|
||||
skb_nfmark(nskb) = 0;
|
||||
skb_init_secmark(nskb);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
|
||||
skb_shinfo(nskb)->gso_size = 0;
|
||||
skb_shinfo(nskb)->gso_segs = 0;
|
||||
skb_shinfo(nskb)->gso_type = 0;
|
||||
#endif
|
||||
|
||||
tcph = (struct tcphdr *)(skb_network_header(nskb) + ip_hdrlen(nskb));
|
||||
|
||||
@@ -177,7 +179,7 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook)
|
||||
|
||||
nf_ct_attach(nskb, oldskb);
|
||||
|
||||
NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
|
||||
NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
|
||||
dst_output);
|
||||
return;
|
||||
|
||||
@@ -186,9 +188,7 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook)
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
tarpit_tg(struct sk_buff **pskb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
tarpit_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
@@ -218,13 +218,14 @@ tarpit_tg(struct sk_buff **pskb, const struct net_device *in,
|
||||
if (iph->frag_off & htons(IP_OFFSET))
|
||||
return NF_DROP;
|
||||
|
||||
tarpit_tcp(*pskb, hooknum);
|
||||
tarpit_tcp(*pskb, par->hooknum);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
static struct xt_target tarpit_tg_reg __read_mostly = {
|
||||
.name = "TARPIT",
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "filter",
|
||||
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
|
||||
.proto = IPPROTO_TCP,
|
||||
|
@@ -142,11 +142,9 @@ static void tee_ip_direct_send(struct sk_buff *skb)
|
||||
* packets when we see they already have that ->nfct.
|
||||
*/
|
||||
static unsigned int
|
||||
tee_tg(struct sk_buff **pskb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
tee_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = targinfo;
|
||||
const struct xt_tee_tginfo *info = par->targinfo;
|
||||
struct sk_buff *skb = *pskb;
|
||||
|
||||
#ifdef WITH_CONNTRACK
|
||||
@@ -169,7 +167,7 @@ tee_tg(struct sk_buff **pskb, const struct net_device *in,
|
||||
* If we are in INPUT, the checksum must be recalculated since
|
||||
* the length could have changed as a result of defragmentation.
|
||||
*/
|
||||
if (hooknum == NF_INET_LOCAL_IN) {
|
||||
if (par->hooknum == NF_INET_LOCAL_IN) {
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
iph->check = 0;
|
||||
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
|
||||
@@ -208,11 +206,9 @@ tee_tg(struct sk_buff **pskb, const struct net_device *in,
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static bool tee_tg_check(const char *tablename, const void *entry,
|
||||
const struct xt_target *target, void *targinfo,
|
||||
unsigned int hook_mask)
|
||||
static bool tee_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = targinfo;
|
||||
const struct xt_tee_tginfo *info = par->targinfo;
|
||||
|
||||
/* 0.0.0.0 and :: not allowed */
|
||||
return memcmp(&info->gw, &zero_address, sizeof(zero_address)) != 0;
|
||||
@@ -220,7 +216,8 @@ static bool tee_tg_check(const char *tablename, const void *entry,
|
||||
|
||||
static struct xt_target tee_tg_reg __read_mostly = {
|
||||
.name = "TEE",
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "mangle",
|
||||
.target = tee_tg,
|
||||
.targetsize = sizeof(struct xt_tee_tginfo),
|
||||
|
@@ -97,12 +97,9 @@ static int condition_proc_write(struct file *file, const char __user *buffer,
|
||||
}
|
||||
|
||||
static bool
|
||||
condition_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, const struct xt_match *match,
|
||||
const void *matchinfo, int offset, unsigned int protoff,
|
||||
bool *hotdrop)
|
||||
condition_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct xt_condition_mtinfo *info = matchinfo;
|
||||
const struct xt_condition_mtinfo *info = par->matchinfo;
|
||||
const struct condition_variable *var = info->condvar;
|
||||
bool x;
|
||||
|
||||
@@ -113,12 +110,9 @@ condition_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
return x ^ info->invert;
|
||||
}
|
||||
|
||||
static bool
|
||||
condition_mt_check(const char *tablename, const void *entry,
|
||||
const struct xt_match *match, void *matchinfo,
|
||||
unsigned int hook_mask)
|
||||
static bool condition_mt_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct xt_condition_mtinfo *info = matchinfo;
|
||||
struct xt_condition_mtinfo *info = par->matchinfo;
|
||||
struct condition_variable *var;
|
||||
|
||||
/* Forbid certain names */
|
||||
@@ -184,9 +178,9 @@ condition_mt_check(const char *tablename, const void *entry,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void condition_mt_destroy(const struct xt_match *match, void *matchinfo)
|
||||
static void condition_mt_destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
const struct xt_condition_mtinfo *info = matchinfo;
|
||||
const struct xt_condition_mtinfo *info = par->matchinfo;
|
||||
struct condition_variable *var = info->condvar;
|
||||
|
||||
down(&proc_lock);
|
||||
@@ -211,7 +205,7 @@ static struct xt_match condition_mt_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "condition",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.matchsize = XT_ALIGN(sizeof(struct xt_condition_mtinfo)),
|
||||
.match = condition_mt,
|
||||
.checkentry = condition_mt_check,
|
||||
@@ -221,7 +215,7 @@ static struct xt_match condition_mt_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "condition",
|
||||
.revision = 0,
|
||||
.family = PF_INET6,
|
||||
.family = NFPROTO_IPV6,
|
||||
.matchsize = XT_ALIGN(sizeof(struct xt_condition_mtinfo)),
|
||||
.match = condition_mt,
|
||||
.checkentry = condition_mt_check,
|
||||
|
@@ -60,12 +60,9 @@ static uint8_t mf_low(uint32_t tx, uint32_t mini, uint32_t maxi)
|
||||
}
|
||||
|
||||
static bool
|
||||
fuzzy_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, const struct xt_match *match,
|
||||
const void *matchinfo, int offset, unsigned int protoff,
|
||||
bool *hotdrop)
|
||||
fuzzy_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
struct xt_fuzzy_mtinfo *info = (void *)matchinfo;
|
||||
struct xt_fuzzy_mtinfo *info = (void *)par->matchinfo;
|
||||
unsigned long amount;
|
||||
uint8_t howhigh, howlow, random_number;
|
||||
|
||||
@@ -128,11 +125,9 @@ fuzzy_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
fuzzy_mt_check(const char *table, const void *ip, const struct xt_match *match,
|
||||
void *matchinfo, unsigned int hook_mask)
|
||||
static bool fuzzy_mt_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct xt_fuzzy_mtinfo *info = matchinfo;
|
||||
const struct xt_fuzzy_mtinfo *info = par->matchinfo;
|
||||
|
||||
if (info->minimum_rate < FUZZY_MIN_RATE ||
|
||||
info->maximum_rate > FUZZY_MAX_RATE ||
|
||||
@@ -148,7 +143,7 @@ static struct xt_match fuzzy_mt_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "fuzzy",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.match = fuzzy_mt,
|
||||
.checkentry = fuzzy_mt_check,
|
||||
.matchsize = XT_ALIGN(sizeof(struct xt_fuzzy_mtinfo)),
|
||||
@@ -157,7 +152,7 @@ static struct xt_match fuzzy_mt_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "fuzzy",
|
||||
.revision = 0,
|
||||
.family = PF_INET6,
|
||||
.family = NFPROTO_IPV6,
|
||||
.match = fuzzy_mt,
|
||||
.checkentry = fuzzy_mt_check,
|
||||
.matchsize = XT_ALIGN(sizeof(struct xt_fuzzy_mtinfo)),
|
||||
|
@@ -135,11 +135,10 @@ static bool geoip_bsearch(const struct geoip_subnet *range,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool xt_geoip_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, const struct xt_match *match,
|
||||
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
|
||||
static bool
|
||||
xt_geoip_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct xt_geoip_match_info *info = matchinfo;
|
||||
const struct xt_geoip_match_info *info = par->matchinfo;
|
||||
const struct geoip_country_kernel *node;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
unsigned int i;
|
||||
@@ -169,10 +168,9 @@ static bool xt_geoip_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
return info->flags & XT_GEOIP_INV;
|
||||
}
|
||||
|
||||
static bool xt_geoip_mt_checkentry(const char *table, const void *entry,
|
||||
const struct xt_match *match, void *matchinfo, unsigned int hook_mask)
|
||||
static bool xt_geoip_mt_checkentry(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct xt_geoip_match_info *info = matchinfo;
|
||||
struct xt_geoip_match_info *info = par->matchinfo;
|
||||
struct geoip_country_kernel *node;
|
||||
unsigned int i;
|
||||
|
||||
@@ -197,9 +195,9 @@ static bool xt_geoip_mt_checkentry(const char *table, const void *entry,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void xt_geoip_mt_destroy(const struct xt_match *match, void *matchinfo)
|
||||
static void xt_geoip_mt_destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
struct xt_geoip_match_info *info = matchinfo;
|
||||
struct xt_geoip_match_info *info = par->matchinfo;
|
||||
struct geoip_country_kernel *node;
|
||||
unsigned int i;
|
||||
|
||||
@@ -223,8 +221,9 @@ static void xt_geoip_mt_destroy(const struct xt_match *match, void *matchinfo)
|
||||
}
|
||||
|
||||
static struct xt_match xt_geoip_match __read_mostly = {
|
||||
.family = AF_INET,
|
||||
.name = "geoip",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.match = xt_geoip_mt,
|
||||
.checkentry = xt_geoip_mt_checkentry,
|
||||
.destroy = xt_geoip_mt_destroy,
|
||||
|
@@ -11,9 +11,9 @@
|
||||
//#define IPP2P_DEBUG_SOUL
|
||||
//#define IPP2P_DEBUG_WINMX
|
||||
|
||||
#define get_u8(X, O) (*(__u8 *)(X + O))
|
||||
#define get_u16(X, O) get_unaligned((__u16 *)(X + O))
|
||||
#define get_u32(X, O) get_unaligned((__u32 *)(X + O))
|
||||
#define get_u8(X, O) (*(const __u8 *)((X) + O))
|
||||
#define get_u16(X, O) get_unaligned((const __u16 *)((X) + O))
|
||||
#define get_u32(X, O) get_unaligned((const __u32 *)((X) + O))
|
||||
|
||||
MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>");
|
||||
MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
|
||||
@@ -785,11 +785,9 @@ static const struct {
|
||||
};
|
||||
|
||||
static bool
|
||||
ipp2p_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, const struct xt_match *match,
|
||||
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
|
||||
ipp2p_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct ipt_p2p_info *info = matchinfo;
|
||||
const struct ipt_p2p_info *info = par->matchinfo;
|
||||
const unsigned char *haystack;
|
||||
const struct iphdr *ip = ip_hdr(skb);
|
||||
bool p2p_result = false;
|
||||
@@ -797,9 +795,9 @@ ipp2p_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
unsigned int hlen = ntohs(ip->tot_len) - ip_hdrlen(skb); /* hlen = packet-data length */
|
||||
|
||||
/* must not be a fragment */
|
||||
if (offset != 0) {
|
||||
if (par->fragoff != 0) {
|
||||
if (info->debug)
|
||||
printk("IPP2P.match: offset found %i \n", offset);
|
||||
printk("IPP2P.match: offset found %d\n", par->fragoff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -869,7 +867,7 @@ ipp2p_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||
static struct xt_match ipp2p_mt_reg __read_mostly = {
|
||||
.name = "ipp2p",
|
||||
.revision = 0,
|
||||
.family = AF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.match = ipp2p_mt,
|
||||
.matchsize = sizeof(struct ipt_p2p_info),
|
||||
.me = THIS_MODULE,
|
||||
|
@@ -171,18 +171,16 @@ static inline unsigned int portscan_mt_full(int mark,
|
||||
return mark;
|
||||
}
|
||||
|
||||
static bool portscan_mt(const struct sk_buff *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
const struct xt_match *match, const void *matchinfo, int offset,
|
||||
unsigned int protoff, bool *hotdrop)
|
||||
static bool
|
||||
portscan_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct xt_portscan_mtinfo *info = matchinfo;
|
||||
const struct xt_portscan_mtinfo *info = par->matchinfo;
|
||||
enum ip_conntrack_info ctstate;
|
||||
const struct tcphdr *tcph;
|
||||
struct nf_conn *ctdata;
|
||||
struct tcphdr tcph_buf;
|
||||
|
||||
tcph = skb_header_pointer(skb, protoff, sizeof(tcph_buf), &tcph_buf);
|
||||
tcph = skb_header_pointer(skb, par->thoff, sizeof(tcph_buf), &tcph_buf);
|
||||
if (tcph == NULL)
|
||||
return false;
|
||||
|
||||
@@ -207,8 +205,8 @@ static bool portscan_mt(const struct sk_buff *skb,
|
||||
unsigned int n;
|
||||
|
||||
n = portscan_mt_full(ctdata->mark & connmark_mask, ctstate,
|
||||
in == init_net__loopback_dev, tcph,
|
||||
skb->len - protoff - 4 * tcph->doff);
|
||||
par->in == init_net__loopback_dev, tcph,
|
||||
skb->len - par->thoff - 4 * tcph->doff);
|
||||
|
||||
ctdata->mark = (ctdata->mark & ~connmark_mask) | n;
|
||||
skb_nfmark(skb) = (skb_nfmark(skb) & ~packet_mask) ^ mark_seen;
|
||||
@@ -219,10 +217,9 @@ static bool portscan_mt(const struct sk_buff *skb,
|
||||
(info->match_gr && ctdata->mark == mark_grscan);
|
||||
}
|
||||
|
||||
static bool portscan_mt_check(const char *tablename, const void *entry,
|
||||
const struct xt_match *match, void *matchinfo, unsigned int hook_mask)
|
||||
static bool portscan_mt_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct xt_portscan_mtinfo *info = matchinfo;
|
||||
const struct xt_portscan_mtinfo *info = par->matchinfo;
|
||||
|
||||
if ((info->match_stealth & ~1) || (info->match_syn & ~1) ||
|
||||
(info->match_cn & ~1) || (info->match_gr & ~1)) {
|
||||
@@ -236,7 +233,7 @@ static struct xt_match portscan_mt_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "portscan",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.match = portscan_mt,
|
||||
.checkentry = portscan_mt_check,
|
||||
.matchsize = sizeof(struct xt_portscan_mtinfo),
|
||||
@@ -246,7 +243,7 @@ static struct xt_match portscan_mt_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "portscan",
|
||||
.revision = 0,
|
||||
.family = PF_INET6,
|
||||
.family = NFPROTO_IPV6,
|
||||
.match = portscan_mt,
|
||||
.checkentry = portscan_mt_check,
|
||||
.matchsize = sizeof(struct xt_portscan_mtinfo),
|
||||
|
@@ -103,7 +103,7 @@ static struct quota_counter *q2_get_counter(const struct xt_quota_mtinfo2 *q)
|
||||
proc_xt_quota);
|
||||
if (p == NULL || IS_ERR(p))
|
||||
goto out;
|
||||
|
||||
|
||||
p->owner = THIS_MODULE;
|
||||
p->data = e;
|
||||
p->read_proc = quota_proc_read;
|
||||
@@ -120,12 +120,9 @@ static struct quota_counter *q2_get_counter(const struct xt_quota_mtinfo2 *q)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
quota_mt2_check(const char *tablename, const void *entry,
|
||||
const struct xt_match *match, void *matchinfo,
|
||||
unsigned int hook_mask)
|
||||
static bool quota_mt2_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct xt_quota_mtinfo2 *q = matchinfo;
|
||||
struct xt_quota_mtinfo2 *q = par->matchinfo;
|
||||
|
||||
if (q->flags & ~XT_QUOTA_MASK)
|
||||
return false;
|
||||
@@ -146,9 +143,9 @@ quota_mt2_check(const char *tablename, const void *entry,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void quota_mt2_destroy(const struct xt_match *match, void *matchinfo)
|
||||
static void quota_mt2_destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
struct xt_quota_mtinfo2 *q = matchinfo;
|
||||
struct xt_quota_mtinfo2 *q = par->matchinfo;
|
||||
struct quota_counter *e = q->master;
|
||||
|
||||
spin_lock_bh(&counter_list_lock);
|
||||
@@ -164,12 +161,9 @@ static void quota_mt2_destroy(const struct xt_match *match, void *matchinfo)
|
||||
}
|
||||
|
||||
static bool
|
||||
quota_mt2(const struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, const struct xt_match *match,
|
||||
const void *matchinfo, int offset, unsigned int protoff,
|
||||
bool *hotdrop)
|
||||
quota_mt2(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
struct xt_quota_mtinfo2 *q = (void *)matchinfo;
|
||||
struct xt_quota_mtinfo2 *q = (void *)par->matchinfo;
|
||||
struct quota_counter *e = q->master;
|
||||
bool ret = q->flags & XT_QUOTA_INVERT;
|
||||
|
||||
@@ -199,7 +193,7 @@ static struct xt_match quota_mt2_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "quota2",
|
||||
.revision = 2,
|
||||
.family = AF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.checkentry = quota_mt2_check,
|
||||
.match = quota_mt2,
|
||||
.destroy = quota_mt2_destroy,
|
||||
@@ -209,7 +203,7 @@ static struct xt_match quota_mt2_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "quota2",
|
||||
.revision = 2,
|
||||
.family = AF_INET6,
|
||||
.family = NFPROTO_IPV6,
|
||||
.checkentry = quota_mt2_check,
|
||||
.match = quota_mt2,
|
||||
.destroy = quota_mt2_destroy,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
.TH xtables-addons 8 2008-04-09
|
||||
.TH xtables\-addons 8 2008\-11\-18
|
||||
.SH NAME
|
||||
Xtables-addons - additional extensions for iptables, ip6tables, etc.
|
||||
Xtables\-addons - additional extensions for iptables, ip6tables, etc.
|
||||
.SH TARGETS
|
||||
.\" @TARGET@
|
||||
.SH MATCHES
|
||||
@@ -8,6 +8,6 @@ Xtables-addons - additional extensions for iptables, ip6tables, etc.
|
||||
.SH "SEE ALSO"
|
||||
\fBiptables\fP(8), \fBip6tables\fP(8)
|
||||
.PP
|
||||
For developers, the book "Writing your own Netfilter modules" at
|
||||
For developers, the book "Writing Netfilter modules" at
|
||||
http://jengelh.medozas.de/documents/Netfilter_Modules.pdf provides detailed
|
||||
information on how to write such modules/extensions.
|
||||
|
Reference in New Issue
Block a user