netfilter: ipset: fix hash size checking in kernel
[linux-flexiantxendom0-3.2.10.git] / net / netfilter / ipset / ip_set_hash_ipportip.c
index 031ed05..52f79d8 100644 (file)
@@ -62,7 +62,8 @@ struct hash_ipportip4_telem {
 
 static inline bool
 hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
-                         const struct hash_ipportip4_elem *ip2)
+                         const struct hash_ipportip4_elem *ip2,
+                         u32 *multi)
 {
        return ip1->ip == ip2->ip &&
               ip1->ip2 == ip2->ip2 &&
@@ -137,6 +138,7 @@ hash_ipportip4_data_next(struct ip_set_hash *h,
 
 static int
 hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
+                   const struct xt_action_param *par,
                    enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
        const struct ip_set_hash *h = set->data;
@@ -160,7 +162,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportip4_elem data = { };
-       u32 ip, ip_to, p = 0, port, port_to;
+       u32 ip, ip_to = 0, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -224,8 +226,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
 
                if (cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
-               ip &= ip_set_hostmask(cidr);
-               ip_to = ip | ~ip_set_hostmask(cidr);
+               ip_set_mask_from_to(ip, ip_to, cidr);
        } else
                ip_to = ip;
 
@@ -286,7 +287,8 @@ struct hash_ipportip6_telem {
 
 static inline bool
 hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
-                         const struct hash_ipportip6_elem *ip2)
+                         const struct hash_ipportip6_elem *ip2,
+                         u32 *multi)
 {
        return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
               ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
@@ -362,6 +364,7 @@ hash_ipportip6_data_next(struct ip_set_hash *h,
 
 static int
 hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
+                   const struct xt_action_param *par,
                    enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
        const struct ip_set_hash *h = set->data;
@@ -464,8 +467,9 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
        struct ip_set_hash *h;
        u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
        u8 hbits;
+       size_t hsize;
 
-       if (!(set->family == AF_INET || set->family == AF_INET6))
+       if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
                return -IPSET_ERR_INVALID_FAMILY;
 
        if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
@@ -491,9 +495,12 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
        h->timeout = IPSET_NO_TIMEOUT;
 
        hbits = htable_bits(hashsize);
-       h->table = ip_set_alloc(
-                       sizeof(struct htable)
-                       + jhash_size(hbits) * sizeof(struct hbucket));
+       hsize = htable_size(hbits);
+       if (hsize == 0) {
+               kfree(h);
+               return -ENOMEM;
+       }
+       h->table = ip_set_alloc(hsize);
        if (!h->table) {
                kfree(h);
                return -ENOMEM;
@@ -505,15 +512,15 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
        if (tb[IPSET_ATTR_TIMEOUT]) {
                h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 
-               set->variant = set->family == AF_INET
+               set->variant = set->family == NFPROTO_IPV4
                        ? &hash_ipportip4_tvariant : &hash_ipportip6_tvariant;
 
-               if (set->family == AF_INET)
+               if (set->family == NFPROTO_IPV4)
                        hash_ipportip4_gc_init(set);
                else
                        hash_ipportip6_gc_init(set);
        } else {
-               set->variant = set->family == AF_INET
+               set->variant = set->family == NFPROTO_IPV4
                        ? &hash_ipportip4_variant : &hash_ipportip6_variant;
        }
 
@@ -529,7 +536,7 @@ static struct ip_set_type hash_ipportip_type __read_mostly = {
        .protocol       = IPSET_PROTOCOL,
        .features       = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
        .dimension      = IPSET_DIM_THREE,
-       .family         = AF_UNSPEC,
+       .family         = NFPROTO_UNSPEC,
        .revision_min   = 0,
        .revision_max   = 1,    /* SCTP and UDPLITE support added */
        .create         = hash_ipportip_create,