These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / netfilter / ipset / ip_set_bitmap_ip.c
index 55b083e..4783eff 100644 (file)
@@ -36,11 +36,11 @@ IP_SET_MODULE_DESC("bitmap:ip", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
 MODULE_ALIAS("ip_set_bitmap:ip");
 
 #define MTYPE          bitmap_ip
+#define HOST_MASK      32
 
 /* Type structure */
 struct bitmap_ip {
        void *members;          /* the set members */
-       void *extensions;       /* data extensions */
        u32 first_ip;           /* host byte order, included in range */
        u32 last_ip;            /* host byte order, included in range */
        u32 elements;           /* number of max elements in the set */
@@ -48,6 +48,8 @@ struct bitmap_ip {
        size_t memsize;         /* members size */
        u8 netmask;             /* subnet netmask */
        struct timer_list gc;   /* garbage collection */
+       unsigned char extensions[0]     /* data extensions */
+               __aligned(__alignof__(u64));
 };
 
 /* ADT structure for generic function args */
@@ -58,7 +60,7 @@ struct bitmap_ip_adt_elem {
 static inline u32
 ip_to_id(const struct bitmap_ip *m, u32 ip)
 {
-       return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
+       return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip) / m->hosts;
 }
 
 /* Common functions */
@@ -80,7 +82,7 @@ static inline int
 bitmap_ip_do_add(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map,
                 u32 flags, size_t dsize)
 {
-       return !!test_and_set_bit(e->id, map->members);
+       return !!test_bit(e->id, map->members);
 }
 
 static inline int
@@ -137,20 +139,17 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
        int ret = 0;
 
-       if (unlikely(!tb[IPSET_ATTR_IP] ||
-                    !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
-                    !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
-                    !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)   ||
-                    !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
-                    !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
-                    !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
-               return -IPSET_ERR_PROTOCOL;
-
        if (tb[IPSET_ATTR_LINENO])
                *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 
-       ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
-             ip_set_get_extensions(set, tb, &ext);
+       if (unlikely(!tb[IPSET_ATTR_IP]))
+               return -IPSET_ERR_PROTOCOL;
+
+       ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
+       if (ret)
+               return ret;
+
+       ret = ip_set_get_extensions(set, tb, &ext);
        if (ret)
                return ret;
 
@@ -174,11 +173,12 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
        } else if (tb[IPSET_ATTR_CIDR]) {
                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 
-               if (!cidr || cidr > 32)
+               if (!cidr || cidr > HOST_MASK)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
+       } else {
                ip_to = ip;
+       }
 
        if (ip_to > map->last_ip)
                return -IPSET_ERR_BITMAP_RANGE;
@@ -189,8 +189,8 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
 
                if (ret && !ip_set_eexist(ret, flags))
                        return ret;
-               else
-                       ret = 0;
+
+               ret = 0;
        }
        return ret;
 }
@@ -225,13 +225,6 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
        map->members = ip_set_alloc(map->memsize);
        if (!map->members)
                return false;
-       if (set->dsize) {
-               map->extensions = ip_set_alloc(set->dsize * elements);
-               if (!map->extensions) {
-                       kfree(map->members);
-                       return false;
-               }
-       }
        map->first_ip = first_ip;
        map->last_ip = last_ip;
        map->elements = elements;
@@ -277,16 +270,17 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
        } else if (tb[IPSET_ATTR_CIDR]) {
                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 
-               if (cidr >= 32)
+               if (cidr >= HOST_MASK)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(first_ip, last_ip, cidr);
-       } else
+       } else {
                return -IPSET_ERR_PROTOCOL;
+       }
 
        if (tb[IPSET_ATTR_NETMASK]) {
                netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
 
-               if (netmask > 32)
+               if (netmask > HOST_MASK)
                        return -IPSET_ERR_INVALID_NETMASK;
 
                first_ip &= ip_set_hostmask(netmask);
@@ -316,13 +310,13 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
        pr_debug("hosts %u, elements %llu\n",
                 hosts, (unsigned long long)elements);
 
-       map = kzalloc(sizeof(*map), GFP_KERNEL);
+       set->dsize = ip_set_elem_len(set, tb, 0, 0);
+       map = ip_set_alloc(sizeof(*map) + elements * set->dsize);
        if (!map)
                return -ENOMEM;
 
        map->memsize = bitmap_bytes(0, elements - 1);
        set->variant = &bitmap_ip;
-       set->dsize = ip_set_elem_len(set, tb, 0);
        if (!init_map_ip(set, map, first_ip, last_ip,
                         elements, hosts, netmask)) {
                kfree(map);
@@ -360,7 +354,8 @@ static struct ip_set_type bitmap_ip_type __read_mostly = {
                [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
                [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
                [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
-               [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING },
+               [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING,
+                                           .len  = IPSET_MAX_COMMENT_SIZE },
                [IPSET_ATTR_SKBMARK]    = { .type = NLA_U64 },
                [IPSET_ATTR_SKBPRIO]    = { .type = NLA_U32 },
                [IPSET_ATTR_SKBQUEUE]   = { .type = NLA_U16 },
@@ -377,6 +372,7 @@ bitmap_ip_init(void)
 static void __exit
 bitmap_ip_fini(void)
 {
+       rcu_barrier();
        ip_set_type_unregister(&bitmap_ip_type);
 }