summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README11
-rw-r--r--kernel/include/linux/netfilter/ip_set.h28
-rw-r--r--kernel/include/linux/netfilter/ip_set_chash.h24
-rw-r--r--kernel/ip_set_bitmap_ip.c6
-rw-r--r--kernel/ip_set_bitmap_ipmac.c4
-rw-r--r--kernel/ip_set_bitmap_port.c6
-rw-r--r--kernel/ip_set_hash_ip.c6
-rw-r--r--kernel/ip_set_hash_ipport.c4
-rw-r--r--kernel/ip_set_hash_ipportip.c4
-rw-r--r--kernel/ip_set_hash_ipportnet.c4
-rw-r--r--kernel/ip_set_hash_net.c4
-rw-r--r--kernel/xt_set.c36
12 files changed, 71 insertions, 66 deletions
diff --git a/README b/README
index 45d3eb9..6c7749f 100644
--- a/README
+++ b/README
@@ -54,3 +54,14 @@ That's it!
Read the ipset(8) and iptables(8), ip6tables(8) manpages on how to use
ipset and its match and target from iptables.
+
+Compatibilities:
+
+- The ipset 5.x userspace utility contains a backward compatibility
+ interface to support the syntax of ipset 4.x.
+- The ipset 5.x userspace utility can't talk to the kernel part of ipset 4.x.
+- The ipset 5.x kernel part can't talk to the userspace utility from
+ ipset 4.x.
+- The ipset 5.x kernel part can work together with the set match and SET
+ target from iptables 1.4.7 and below, however if you need the IPv6 support
+ from ipset 5.x, then you have to use iptables 1.4.8 or above.
diff --git a/kernel/include/linux/netfilter/ip_set.h b/kernel/include/linux/netfilter/ip_set.h
index b83454a..1c41396 100644
--- a/kernel/include/linux/netfilter/ip_set.h
+++ b/kernel/include/linux/netfilter/ip_set.h
@@ -245,13 +245,6 @@ struct ip_set_type_variant {
bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
};
-/* Flags for the set type variants */
-enum ip_set_type_flags {
- /* Set members created by kmalloc */
- IP_SET_FLAG_KMALLOC_BIT = 0,
- IP_SET_FLAG_KMALLOC = (1 << IP_SET_FLAG_KMALLOC_BIT),
-};
-
/* The core set type structure */
struct ip_set_type {
struct list_head list;
@@ -294,8 +287,6 @@ struct ip_set {
const struct ip_set_type_variant *variant;
/* The actual INET family */
u8 family;
- /* Set type flags, filled/modified by create/resize */
- u8 flags;
/* The type specific data */
void *data;
};
@@ -318,12 +309,14 @@ extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
/* Allocate members */
static inline void *
-ip_set_alloc(size_t size, gfp_t gfp_mask, u8 *flags)
+ip_set_alloc(size_t size, gfp_t gfp_mask)
{
- void *members = kzalloc(size, gfp_mask | __GFP_NOWARN);
+ void *members = NULL;
+
+ if (size < KMALLOC_MAX_SIZE)
+ members = kzalloc(size, gfp_mask | __GFP_NOWARN);
if (members) {
- *flags |= IP_SET_FLAG_KMALLOC;
pr_debug("%p: allocated with kmalloc", members);
return members;
}
@@ -331,21 +324,20 @@ ip_set_alloc(size_t size, gfp_t gfp_mask, u8 *flags)
members = __vmalloc(size, gfp_mask | __GFP_ZERO, PAGE_KERNEL);
if (!members)
return NULL;
- *flags &= ~IP_SET_FLAG_KMALLOC;
pr_debug("%p: allocated with vmalloc", members);
return members;
}
static inline void
-ip_set_free(void *members, u8 flags)
+ip_set_free(void *members)
{
pr_debug("%p: free with %s", members,
- flags & IP_SET_FLAG_KMALLOC ? "kmalloc" : "vmalloc");
- if (flags & IP_SET_FLAG_KMALLOC)
- kfree(members);
- else
+ is_vmalloc_addr(members) ? "vfree" : "kfree");
+ if (is_vmalloc_addr(members))
vfree(members);
+ else
+ kfree(members);
}
static inline bool
diff --git a/kernel/include/linux/netfilter/ip_set_chash.h b/kernel/include/linux/netfilter/ip_set_chash.h
index e0e16bd..5e615e4 100644
--- a/kernel/include/linux/netfilter/ip_set_chash.h
+++ b/kernel/include/linux/netfilter/ip_set_chash.h
@@ -86,7 +86,7 @@ del_cidr(struct chash_nets *nets, u8 host_mask, u8 cidr)
}
static void
-chash_destroy(struct slist *t, u8 htable_bits, u8 flags)
+chash_destroy(struct slist *t, u8 htable_bits)
{
struct slist *n, *tmp;
u32 i;
@@ -96,7 +96,7 @@ chash_destroy(struct slist *t, u8 htable_bits, u8 flags)
/* FIXME: slab cache */
kfree(n);
- ip_set_free(t, flags);
+ ip_set_free(t);
}
static size_t
@@ -146,7 +146,7 @@ ip_set_hash_destroy(struct ip_set *set)
if (with_timeout(h->timeout))
del_timer_sync(&h->gc);
- chash_destroy(h->htable, h->htable_bits, set->flags);
+ chash_destroy(h->htable, h->htable_bits);
kfree(h);
set->data = NULL;
@@ -296,7 +296,6 @@ type_pf_resize(struct ip_set *set, gfp_t gfp_flags, bool retried)
struct slist *t, *n;
const struct type_pf_elem *data;
u32 i, j;
- u8 oflags, flags;
int ret;
retry:
@@ -306,12 +305,11 @@ retry:
/* In case we have plenty of memory :-) */
return -IPSET_ERR_HASH_FULL;
t = ip_set_alloc(jhash_size(htable_bits) * sizeof(struct slist),
- gfp_flags, &flags);
+ gfp_flags);
if (!t)
return -ENOMEM;
write_lock_bh(&set->lock);
- flags = oflags = set->flags;
for (i = 0; i < jhash_size(h->htable_bits); i++) {
next_slot:
slist_for_each(n, &h->htable[i]) {
@@ -325,7 +323,7 @@ next_slot:
data, gfp_flags);
if (ret < 0) {
write_unlock_bh(&set->lock);
- chash_destroy(t, htable_bits, flags);
+ chash_destroy(t, htable_bits);
if (ret == -EAGAIN)
goto retry;
return ret;
@@ -339,10 +337,9 @@ next_slot:
h->htable = t;
h->htable_bits = htable_bits;
- set->flags = flags;
write_unlock_bh(&set->lock);
- chash_destroy(n, i, oflags);
+ chash_destroy(n, i);
return 0;
}
@@ -750,7 +747,6 @@ type_pf_tresize(struct ip_set *set, gfp_t gfp_flags, bool retried)
struct slist *t, *n;
const struct type_pf_elem *data;
u32 i, j;
- u8 oflags, flags;
int ret;
/* Try to cleanup once */
@@ -770,12 +766,11 @@ retry:
/* In case we have plenty of memory :-) */
return -IPSET_ERR_HASH_FULL;
t = ip_set_alloc(jhash_size(htable_bits) * sizeof(struct slist),
- gfp_flags, &flags);
+ gfp_flags);
if (!t)
return -ENOMEM;
write_lock_bh(&set->lock);
- flags = oflags = set->flags;
for (i = 0; i < jhash_size(h->htable_bits); i++) {
next_slot:
slist_for_each(n, &h->htable[i]) {
@@ -790,7 +785,7 @@ next_slot:
type_pf_data_timeout(data));
if (ret < 0) {
write_unlock_bh(&set->lock);
- chash_destroy(t, htable_bits, flags);
+ chash_destroy(t, htable_bits);
if (ret == -EAGAIN)
goto retry;
return ret;
@@ -804,10 +799,9 @@ next_slot:
h->htable = t;
h->htable_bits = htable_bits;
- set->flags = flags;
write_unlock_bh(&set->lock);
- chash_destroy(n, i, oflags);
+ chash_destroy(n, i);
return 0;
}
diff --git a/kernel/ip_set_bitmap_ip.c b/kernel/ip_set_bitmap_ip.c
index e63bcda..76baa13 100644
--- a/kernel/ip_set_bitmap_ip.c
+++ b/kernel/ip_set_bitmap_ip.c
@@ -180,7 +180,7 @@ bitmap_ip_destroy(struct ip_set *set)
{
struct bitmap_ip *map = set->data;
- ip_set_free(map->members, set->flags);
+ ip_set_free(map->members);
kfree(map);
set->data = NULL;
@@ -423,7 +423,7 @@ bitmap_ip_timeout_destroy(struct ip_set *set)
struct bitmap_ip_timeout *map = set->data;
del_timer_sync(&map->gc);
- ip_set_free(map->members, set->flags);
+ ip_set_free(map->members);
kfree(map);
set->data = NULL;
@@ -575,7 +575,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
u32 first_ip, u32 last_ip,
u32 elements, u32 hosts, u8 netmask)
{
- map->members = ip_set_alloc(map->memsize, GFP_KERNEL, &set->flags);
+ map->members = ip_set_alloc(map->memsize, GFP_KERNEL);
if (!map->members)
return false;
map->first_ip = first_ip;
diff --git a/kernel/ip_set_bitmap_ipmac.c b/kernel/ip_set_bitmap_ipmac.c
index 5833c77..c595e18 100644
--- a/kernel/ip_set_bitmap_ipmac.c
+++ b/kernel/ip_set_bitmap_ipmac.c
@@ -423,7 +423,7 @@ bitmap_ipmac_destroy(struct ip_set *set)
if (with_timeout(map->timeout))
del_timer_sync(&map->gc);
- ip_set_free(map->members, set->flags);
+ ip_set_free(map->members);
kfree(map);
set->data = NULL;
@@ -553,7 +553,7 @@ init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
u32 first_ip, u32 last_ip)
{
map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize,
- GFP_KERNEL, &set->flags);
+ GFP_KERNEL);
if (!map->members)
return false;
map->first_ip = first_ip;
diff --git a/kernel/ip_set_bitmap_port.c b/kernel/ip_set_bitmap_port.c
index c96b06c..c385f99 100644
--- a/kernel/ip_set_bitmap_port.c
+++ b/kernel/ip_set_bitmap_port.c
@@ -166,7 +166,7 @@ bitmap_port_destroy(struct ip_set *set)
{
struct bitmap_port *map = set->data;
- ip_set_free(map->members, set->flags);
+ ip_set_free(map->members);
kfree(map);
set->data = NULL;
@@ -403,7 +403,7 @@ bitmap_port_timeout_destroy(struct ip_set *set)
struct bitmap_port_timeout *map = set->data;
del_timer_sync(&map->gc);
- ip_set_free(map->members, set->flags);
+ ip_set_free(map->members);
kfree(map);
set->data = NULL;
@@ -551,7 +551,7 @@ static bool
init_map_port(struct ip_set *set, struct bitmap_port *map,
u16 first_port, u16 last_port)
{
- map->members = ip_set_alloc(map->memsize, GFP_KERNEL, &set->flags);
+ map->members = ip_set_alloc(map->memsize, GFP_KERNEL);
if (!map->members)
return false;
map->first_port = first_port;
diff --git a/kernel/ip_set_hash_ip.c b/kernel/ip_set_hash_ip.c
index 1af96ac..3295b26 100644
--- a/kernel/ip_set_hash_ip.c
+++ b/kernel/ip_set_hash_ip.c
@@ -212,11 +212,11 @@ hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
{
struct chash *x = a->data;
struct chash *y = b->data;
-
+
+ /* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout
&& x->netmask == y->netmask
- && x->htable_bits == y->htable_bits /* resizing ? */
&& x->array_size == y->array_size
&& x->chain_limit == y->chain_limit;
}
@@ -431,7 +431,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
h->timeout = IPSET_NO_TIMEOUT;
h->htable = ip_set_alloc(jhash_size(h->htable_bits) * sizeof(struct slist),
- GFP_KERNEL, &set->flags);
+ GFP_KERNEL);
if (!h->htable) {
kfree(h);
return -ENOMEM;
diff --git a/kernel/ip_set_hash_ipport.c b/kernel/ip_set_hash_ipport.c
index f0274f9..8554c80 100644
--- a/kernel/ip_set_hash_ipport.c
+++ b/kernel/ip_set_hash_ipport.c
@@ -229,10 +229,10 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
struct chash *x = a->data;
struct chash *y = b->data;
+ /* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout
&& x->proto == y->proto
- && x->htable_bits == y->htable_bits /* resizing ? */
&& x->array_size == y->array_size
&& x->chain_limit == y->chain_limit;
}
@@ -473,7 +473,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
h->timeout = IPSET_NO_TIMEOUT;
h->htable = ip_set_alloc(jhash_size(h->htable_bits) * sizeof(struct slist),
- GFP_KERNEL, &set->flags);
+ GFP_KERNEL);
if (!h->htable) {
kfree(h);
return -ENOMEM;
diff --git a/kernel/ip_set_hash_ipportip.c b/kernel/ip_set_hash_ipportip.c
index 16e6f17..d2db3a9 100644
--- a/kernel/ip_set_hash_ipportip.c
+++ b/kernel/ip_set_hash_ipportip.c
@@ -241,10 +241,10 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
struct chash *x = a->data;
struct chash *y = b->data;
+ /* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout
&& x->proto == y->proto
- && x->htable_bits == y->htable_bits /* resizing ? */
&& x->array_size == y->array_size
&& x->chain_limit == y->chain_limit;
}
@@ -500,7 +500,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
h->timeout = IPSET_NO_TIMEOUT;
h->htable = ip_set_alloc(jhash_size(h->htable_bits) * sizeof(struct slist),
- GFP_KERNEL, &set->flags);
+ GFP_KERNEL);
if (!h->htable) {
kfree(h);
return -ENOMEM;
diff --git a/kernel/ip_set_hash_ipportnet.c b/kernel/ip_set_hash_ipportnet.c
index f356a88..f2c0d07 100644
--- a/kernel/ip_set_hash_ipportnet.c
+++ b/kernel/ip_set_hash_ipportnet.c
@@ -270,10 +270,10 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
struct chash *x = a->data;
struct chash *y = b->data;
+ /* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout
&& x->proto == y->proto
- && x->htable_bits == y->htable_bits /* resizing ? */
&& x->array_size == y->array_size
&& x->chain_limit == y->chain_limit;
}
@@ -567,7 +567,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
h->timeout = IPSET_NO_TIMEOUT;
h->htable = ip_set_alloc(jhash_size(h->htable_bits) * sizeof(struct slist),
- GFP_KERNEL, &set->flags);
+ GFP_KERNEL);
if (!h->htable) {
kfree(h);
return -ENOMEM;
diff --git a/kernel/ip_set_hash_net.c b/kernel/ip_set_hash_net.c
index 42112a2..6b755ce 100644
--- a/kernel/ip_set_hash_net.c
+++ b/kernel/ip_set_hash_net.c
@@ -211,9 +211,9 @@ hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
struct chash *x = a->data;
struct chash *y = b->data;
+ /* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout
- && x->htable_bits == y->htable_bits /* resizing ? */
&& x->array_size == y->array_size
&& x->chain_limit == y->chain_limit;
}
@@ -442,7 +442,7 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
h->timeout = IPSET_NO_TIMEOUT;
h->htable = ip_set_alloc(jhash_size(h->htable_bits) * sizeof(struct slist),
- GFP_KERNEL, &set->flags);
+ GFP_KERNEL);
if (!h->htable) {
kfree(h);
return -ENOMEM;
diff --git a/kernel/xt_set.c b/kernel/xt_set.c
index 4734cc4..05bd84e 100644
--- a/kernel/xt_set.c
+++ b/kernel/xt_set.c
@@ -49,6 +49,14 @@ match_set(ip_set_id_t index, const struct sk_buff *skb,
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+#define CHECK_OK 1
+#define CHECK_FAIL 0
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
+#define CHECK_OK 0
+#define CHECK_FAIL -EINVAL
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
static bool
set_match_v0(const struct sk_buff *skb, const struct xt_match_param *par)
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
@@ -96,17 +104,17 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par)
if (index == IPSET_INVALID_ID) {
pr_warning("Cannot find set indentified by id %u to match",
info->match_set.index);
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
pr_warning("That's nasty!");
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
/* Fill out compatibility data */
compat_flags(&info->match_set);
- return 1;
+ return CHECK_OK;
}
static void
@@ -155,7 +163,7 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find add_set index %u as target",
info->add_set.index);
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
}
@@ -164,20 +172,20 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find del_set index %u as target",
info->del_set.index);
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
}
if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0
|| info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
pr_warning("That's nasty!");
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
/* Fill out compatibility data */
compat_flags(&info->add_set);
compat_flags(&info->del_set);
- return 1;
+ return CHECK_OK;
}
static void
@@ -225,14 +233,14 @@ set_match_checkentry(const struct xt_mtchk_param *par)
if (index == IPSET_INVALID_ID) {
pr_warning("Cannot find set indentified by id %u to match",
info->match_set.index);
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
if (info->match_set.dim > IPSET_DIM_MAX) {
pr_warning("That's nasty!");
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
- return 1;
+ return CHECK_OK;
}
static void
@@ -283,7 +291,7 @@ set_target_checkentry(const struct xt_tgchk_param *par)
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find add_set index %u as target",
info->add_set.index);
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
}
@@ -292,16 +300,16 @@ set_target_checkentry(const struct xt_tgchk_param *par)
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find del_set index %u as target",
info->del_set.index);
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
}
if (info->add_set.dim > IPSET_DIM_MAX
|| info->del_set.flags > IPSET_DIM_MAX) {
pr_warning("That's nasty!");
- return 0; /* error */
+ return CHECK_FAIL; /* error */
}
- return 1;
+ return CHECK_OK;
}
static void