]> granicus.if.org Git - ipset/commitdiff
Cleanup, compatibility v5.0-pre7
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Mon, 23 Aug 2010 14:48:14 +0000 (16:48 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Mon, 23 Aug 2010 14:48:14 +0000 (16:48 +0200)
- Use is_vmalloc_addr when freeing vmalloc or kmalloc-ed areas. Thus
  we can get rid of a flag and simplify some functions.
- When checking "same" sets, ignore hash size, because resizing
  changes it.
- 2.6.35 compatibility added.
- Discuss backward/forward compatibilities in the README file.

12 files changed:
README
kernel/include/linux/netfilter/ip_set.h
kernel/include/linux/netfilter/ip_set_chash.h
kernel/ip_set_bitmap_ip.c
kernel/ip_set_bitmap_ipmac.c
kernel/ip_set_bitmap_port.c
kernel/ip_set_hash_ip.c
kernel/ip_set_hash_ipport.c
kernel/ip_set_hash_ipportip.c
kernel/ip_set_hash_ipportnet.c
kernel/ip_set_hash_net.c
kernel/xt_set.c

diff --git a/README b/README
index 45d3eb96a4e82703d3135fd42d62f049b0eb33e4..6c7749f0c1329de3d68478ef5059328337013de0 100644 (file)
--- 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.
index b83454ad0e91a3afe01ff46c7126ae1067ebe43f..1c41396ace46d087813b27a330961b8195da05d9 100644 (file)
@@ -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
index e0e16bd7b12610f8283696e73ffbb2c7219d2461..5e615e4b88ec9bef7872fd2c0ba7f9402154e62c 100644 (file)
@@ -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;
 }
index e63bcda7c6a67cf8dbf80d064a24e42729b0f7ea..76baa13f567a1b16fda4e6fbc4be655fdaa5621a 100644 (file)
@@ -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;
index 5833c7779b9445dc579a774e64e14e1fed3e1273..c595e189ead65a19cec6650c2f6c55e1c3b33769 100644 (file)
@@ -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;
index c96b06c656135bd772e813d0d16402847b83a6a7..c385f990d39e8d2e91ab4c736da264d06aea7ce0 100644 (file)
@@ -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;
index 1af96acb81348c17311a8a7788fea48f38f67681..3295b264305d37fb6f9aaa19c5911495b2b41e59 100644 (file)
@@ -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;
index f0274f958adaebf8b94cc8ffe43c82c39ef46a91..8554c80f8556fa657d56e733486696bb95a0da0a 100644 (file)
@@ -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;
index 16e6f174eedb6c89f79c57e0f1e89a0d8d08c1c2..d2db3a92ff1181064abed10175f9d79433a75ca9 100644 (file)
@@ -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;
index f356a88b767b12d899c9d590ee2f79fd0dafd3e9..f2c0d07fe780ec4c9bcff77eb83251a2e8a4b320 100644 (file)
@@ -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;
index 42112a21870fd95a91c132cdb20976697aa645f1..6b755ce66422a336b7deb224be5a237317937d4c 100644 (file)
@@ -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;
index 4734cc42ca7246c32a8b6ebd30a41a53b8b56182..05bd84eb1b55b87e1d7e45ee5d0192975c227cc3 100644 (file)
@@ -48,6 +48,14 @@ match_set(ip_set_id_t index, const struct sk_buff *skb,
 #error "Linux kernel version too old: must be >= 2.6.31"
 #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)
@@ -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